Skip to content

Commit

Permalink
upgrade to latest soroban client to fix errors getting contract data …
Browse files Browse the repository at this point in the history
…(seems the interface / XDR has changed ...)

implement operation claim_claimable_balance
improve rendering of ScVals - handle bigints nested in objects
  • Loading branch information
chatch committed Sep 19, 2023
1 parent 2265bc1 commit 95b7af7
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 31 deletions.
13 changes: 11 additions & 2 deletions app/components/operations/ClaimableBalances.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,17 @@ const CreateClaimableBalanceOperation = ({ amount, sponsor, asset }: any) => {
const [assetCode, assetIssuer] = asset.split(':')
return (
<span>
<AccountLink account={sponsor} /> created claimable balance for {amount} <Asset code={assetCode} issuer={assetIssuer} type="unknown" /></span>
<AccountLink account={sponsor} /> created claimable balance for {amount} <Asset code={assetCode} issuer={assetIssuer} type="unknown" />
</span>
)
}

export { CreateClaimableBalanceOperation }
const ClaimClaimableBalanceOperation = ({ claimant }: any) => {
return (
<span>
Claimant <AccountLink account={claimant} />
</span>
)
}

export { ClaimClaimableBalanceOperation, CreateClaimableBalanceOperation }
3 changes: 2 additions & 1 deletion app/components/operations/Operation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import AccountMerge from "./AccountMerge"
import AllowTrust, { AllowTrustProps } from "./AllowTrust"
import BumpSequence from "./BumpSequence"
import ChangeTrust from "./ChangeTrust"
import { CreateClaimableBalanceOperation } from "./ClaimableBalances"
import { ClaimClaimableBalanceOperation, CreateClaimableBalanceOperation } from "./ClaimableBalances"
import CreateAccount, { CreateAccountProps } from "./CreateAccount"
import Inflation from "./Inflation"
import InvokeHostFunction from "./InvokeHostFunction"
Expand All @@ -31,6 +31,7 @@ const OperationTypeToComponentMap = {
create_passive_sell_offer: Offer,
create_passive_offer: Offer, // < Protocol 11

claim_claimable_balance: ClaimClaimableBalanceOperation,
create_claimable_balance: CreateClaimableBalanceOperation,

inflation: Inflation,
Expand Down
24 changes: 15 additions & 9 deletions app/lib/stellar/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,25 @@ const getContractInfo = async (
new xdr.LedgerKeyContractData({
contract: new Contract(contractId).address().toScAddress(),
key: xdr.ScVal.scvLedgerKeyContractInstance(),
durability: xdr.ContractDataDurability.persistent(),
bodyType: xdr.ContractEntryBodyType.dataEntry()
durability: xdr.ContractDataDurability.persistent()
})
)

const ledgerEntries = await server.getLedgerEntries([ledgerKey])
let ledgerEntries
try {

ledgerEntries = await server.getLedgerEntries(ledgerKey)
} catch (error) {
console.error(error)
}

if (ledgerEntries == null || ledgerEntries.entries == null) {
return null
}

const ledgerEntry = ledgerEntries.entries[0]
const codeData = xdr.LedgerEntryData.fromXDR(ledgerEntry.xdr, 'base64')
.contractData().body().data()
.contractData()

const wasmIdLedger = ledgerEntry.lastModifiedLedgerSeq

Expand All @@ -69,11 +75,10 @@ const getContractCode = async (
): Promise<{ wasmCode: string, wasmCodeLedger: number } | null> => {
const ledgerKey = xdr.LedgerKey.contractCode(
new xdr.LedgerKeyContractCode({
hash: wasmId,
bodyType: xdr.ContractEntryBodyType.dataEntry()
hash: wasmId
})
)
const ledgerEntries = await server.getLedgerEntries([ledgerKey])
const ledgerEntries = await server.getLedgerEntries(ledgerKey)
if (ledgerEntries == null || ledgerEntries.entries == null) {
return null
}
Expand All @@ -82,7 +87,7 @@ const getContractCode = async (
const wasmCodeLedger = ledgerEntry.lastModifiedLedgerSeq as number

const codeEntry = xdr.LedgerEntryData.fromXDR(ledgerEntry.xdr, 'base64')
const wasmCode = codeEntry.contractCode().body().code().toString('hex')
const wasmCode = codeEntry.contractCode().code().toString('hex')

return { wasmCode, wasmCodeLedger }
}
Expand Down Expand Up @@ -111,8 +116,9 @@ const loadContract = async (
}

const { wasmId, wasmIdLedger } = wasmIdResult
// console.log(`wasmIdResult ${JSON.stringify(wasmIdResult, null, 2)}`)
if (!wasmId) {
console.error('Failed to get wasm id')
console.warn('no wasmId not in result')
return
}

Expand Down
4 changes: 2 additions & 2 deletions app/lib/stellar/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const requestToServer = (request: Request): HorizonServer => {

const requestToSorobanServer = (request: Request): SorobanServer => {
const { networkType } = requestToNetworkDetails(request)
if (![networks.future, networks.local].includes(networkType)) {
throw new Error(`network ${networkType} not yet supported by Soroban / Stellar Explorer`)
if (![networks.future, networks.test, networks.local].includes(networkType)) {
throw new Error(`Soroban smart contracts not yet supported on the network [${networkType}].`)
}
return new SorobanServer(
networkType,
Expand Down
39 changes: 34 additions & 5 deletions app/lib/stellar/xdr_scval_utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { StrKey, scValToNative, xdr } from 'soroban-client'

const Buffer = require('buffer').Buffer

export function scValToAddress(
scval: any // : SorobanClient.xdr.ScVal | undefined
): string {
Expand All @@ -14,17 +16,44 @@ export function scValToAddress(
}
}

export const scValToString = (scVal: any) => {
console.log(`type ${scVal.switch ? scVal.switch().name : 'unknown'}`)
const native = scValToNative(scVal)
console.log(`type: ${typeof native} val: ${native}`)
/**
* Takes a value returned by scValToNative (some js type) and converts it to a string.
*
* Handles:
* - bigint - JSON.stringify can't handle it
* - Buffer - ensure hex string returned
* - values nested in objects or arrays
*
* @param native some javascript value to be converted to a string
* @returns string representation
*/
const jsNativeValToString = (native: any): string => {
// console.log(`type=${typeof native}`)
if (typeof native === 'string') {
return native
} else if (typeof native === 'bigint') {
return native.toString()
} else if (Array.isArray(native)) {
return native.map(val => typeof val === 'bigint' ? val.toString() : val)
return JSON.stringify(native.map(val => jsNativeValToString(val)))
} else if (typeof native === 'object') {
return jsNativeObjectValToString(native)
} else if (Buffer.isBuffer(native)) {
return native.toString('hex')
} else {
return JSON.stringify(native)
}
}

const jsNativeObjectValToString = (native: any): string => {
const convertedObj: Record<string, string> = {}
for (const [objKey, objVal] of Object.entries(native)) {
// console.log(`key ${JSON.stringify(objKey, null, 2)}`)
convertedObj[objKey] = jsNativeValToString(objVal)
}
return JSON.stringify(convertedObj)
}

export const scValToString = (scVal: any): string => {
const native = scValToNative(scVal)
return jsNativeValToString(native)
}
2 changes: 1 addition & 1 deletion app/routes/account.$accountId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export const loader = async ({ params, request }: LoaderArgs) => {
if (error instanceof NotFoundError) {
throw new Response(null, {
status: 404,
statusText: `Account not found`,
statusText: `Account [${params.accountId}] not found on this network.`,
})
} else if (error instanceof AccountTypeUnrecognizedException) {
throw new Response(null, {
Expand Down
2 changes: 1 addition & 1 deletion app/routes/ledger.$ledgerId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const loader = async ({ params, request }: LoaderArgs) => {
const ledgerSeq = params.ledgerId as string
return Promise.all([
ledger(server, ledgerSeq),
transactions(server, { ledgerSeq }),
transactions(server, { ledgerSeq, limit: 100 }),
server.serverURL.toString()
]).then(json)
}
Expand Down
2 changes: 1 addition & 1 deletion app/routes/tx.$txHash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const loader = ({ params, request }: LoaderArgs) => {
const server = requestToServer(request)
return Promise.all([
transaction(server, params.txHash as string),
operations(server, { tx: params.txHash, limit: 10 }),
operations(server, { tx: params.txHash, limit: 100 }),
server.serverURL.toString()
]).then(json)
}
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"react-json-pretty": "^2.2.0",
"react-router-bootstrap": "^0.26.2",
"remix-utils": "^6.6.0",
"soroban-client": "0.11.2",
"soroban-client": "1.0.0-beta.2",
"stellar-sdk": "10.4.1",
"urijs": "1.19.11"
},
Expand Down

0 comments on commit 95b7af7

Please sign in to comment.