From def82f14d8182c0544bf491670f77d605c0b6bc3 Mon Sep 17 00:00:00 2001 From: George Date: Thu, 14 Nov 2024 10:38:57 -0800 Subject: [PATCH] Add support for `buildInvocationTree` to parse V2 of creation calls (#784) * Release v13.0.1 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- src/invocation.js | 22 +++++++++++++++++----- test/unit/invocation_test.js | 14 ++++++++++---- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a59a05a..601a3faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ ## Unreleased +## [`v13.0.1`](https://github.com/stellar/js-stellar-base/compare/v13.0.0...v13.0.1) + +### Fixed +* `buildInvocationTree` will now successfully walk creation invocations with constructor arguments ([#784](https://github.com/stellar/js-stellar-base/pull/784)). + + ## [`v13.0.0`](https://github.com/stellar/js-stellar-base/compare/v12.1.1...v13.0.0) **This release supports Protocol 22.** While the network has not upgraded yet, you can start integrating the new features into your codebase if you want a head start. Keep in mind that while the binary XDR is backwards-compatible, the naming and layout of structures is not. In other words, this build will continue to work on Protocol 21, but you may have to update code that references XDR directly. diff --git a/package.json b/package.json index 2f5a204b..fc6f128c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@stellar/stellar-base", - "version": "13.0.0", + "version": "13.0.1", "description": "Low-level support library for the Stellar network.", "main": "./lib/index.js", "browser": { diff --git a/src/invocation.js b/src/invocation.js index c2a77590..344b3571 100644 --- a/src/invocation.js +++ b/src/invocation.js @@ -15,6 +15,9 @@ import { scValToNative } from './scval'; * @prop {string} wasm.address contract address of this deployment * @prop {string} wasm.salt hex salt that the user consumed when creating * this contract (encoded in the resulting address) + * @prop {any[]} [wasm.constructorArgs] a list of natively-represented values + * (see {@link scValToNative}) that are passed to the constructor when + * creating this contract */ /** @@ -23,8 +26,8 @@ import { scValToNative } from './scval'; * @prop {string} source the strkey of the contract (C...) being invoked * @prop {string} function the name of the function being invoked * @prop {any[]} args the natively-represented parameters to the function - * invocation (see {@link scValToNative}) for rules on how they're - * represented a JS types + * invocation (see {@link scValToNative} for rules on how they're + * represented a JS types) */ /** @@ -85,7 +88,7 @@ export function buildInvocationTree(root) { /** @type {InvocationTree} */ const output = {}; - /** @type {xdr.CreateContractArgs | xdr.InvokeContractArgs} */ + /** @type {xdr.CreateContractArgs|xdr.CreateContractArgsV2|xdr.InvokeContractArgs} */ const inner = fn.value(); switch (fn.switch().value) { @@ -100,7 +103,10 @@ export function buildInvocationTree(root) { break; // sorobanAuthorizedFunctionTypeCreateContractHostFn - case 1: { + // sorobanAuthorizedFunctionTypeCreateContractV2HostFn + case 1: // fallthrough: just no ctor args in V1 + case 2: { + const createV2 = fn.switch().value === 2; output.type = 'create'; output.args = {}; @@ -130,7 +136,13 @@ export function buildInvocationTree(root) { output.args.wasm = { salt: details.salt().toString('hex'), hash: exec.wasmHash().toString('hex'), - address: Address.fromScAddress(details.address()).toString() + address: Address.fromScAddress(details.address()).toString(), + // only apply constructor args for WASM+CreateV2 scenario + ...(createV2 && { + constructorArgs: inner + .constructorArgs() + .map((arg) => scValToNative(arg)) + }) // empty indicates V2 and no ctor, undefined indicates V1 }; break; } diff --git a/test/unit/invocation_test.js b/test/unit/invocation_test.js index d67c0c3e..a7f6b7cf 100644 --- a/test/unit/invocation_test.js +++ b/test/unit/invocation_test.js @@ -30,7 +30,7 @@ const { // | // +--- someNft.transfer(invoker, someNft, 2) // | -// +--- create(custom wasm contract) +// +--- createV2(custom wasm contract) function rk() { return Keypair.random().publicKey(); } @@ -116,8 +116,8 @@ describe('parsing invocation trees', function () { }), new xdr.SorobanAuthorizedInvocation({ function: - xdr.SorobanAuthorizedFunction.sorobanAuthorizedFunctionTypeCreateContractHostFn( - new xdr.CreateContractArgs({ + xdr.SorobanAuthorizedFunction.sorobanAuthorizedFunctionTypeCreateContractV2HostFn( + new xdr.CreateContractArgsV2({ contractIdPreimage: xdr.ContractIdPreimage.contractIdPreimageFromAddress( new xdr.ContractIdPreimageFromAddress({ @@ -125,6 +125,11 @@ describe('parsing invocation trees', function () { salt: Buffer.alloc(32, 0) }) ), + constructorArgs: [1, '2', 3].map((arg, i) => { + return nativeToScVal(arg, { + type: ['u32', 'string', 'i32'][i] + }); + }), executable: xdr.ContractExecutable.contractExecutableWasm( Buffer.alloc(32, '\x20') ) @@ -196,7 +201,8 @@ describe('parsing invocation trees', function () { wasm: { salt: '00'.repeat(32), hash: '20'.repeat(32), - address: nftContract.contractId() + address: nftContract.contractId(), + constructorArgs: [1, '2', 3] } }, invocations: []