CityOfZion / neon-js

Javascript libraries that allow the applications to interact with NEO blockchain
https://docs.coz.io/neo3/neon-js/index.html
MIT License
183 stars 165 forks source link

Issue when serializing transactions #875

Closed EdgeDLT closed 1 year ago

EdgeDLT commented 1 year ago

Trying to set up a way to create multi-sig transactions that can be imported and signed in Neon. I was following this guide to get up and running when I ran into the issue during the checkNetworkFee step.

It seems transaction.serialize() will error depending on which properties have been added to the transaction object. Here's a runnable example of what I'm talking about:

import { CONST, rpc, sc, wallet, tx, u } from "@cityofzion/neon-js"

const dev = new wallet.Account()
const url = "http://test.neo3.edgeofneo.com:20332"
const node = new rpc.RPCClient(url)

let currentHeight = await node.getBlockCount()

let transaction = new tx.Transaction()

console.log(transaction.serialize())
// 00fc3e502c000000000000000000000000000000000000000000000000

transaction.systemFee = new u.BigInteger(1)
transaction.networkFee = new u.BigInteger(1)
transaction.systemFee = new u.BigInteger(1)
transaction.validUntilBlock = currentHeight + 1000

console.log(transaction.serialize())
// 00fc3e502c01000000000000000100000000000000ea400f0000000000

let script = sc.createScript({
    scriptHash: CONST.NATIVE_CONTRACT_HASH.GasToken,
    operation: "transfer",
    args: [
        sc.ContractParam.hash160(dev.address),
        sc.ContractParam.hash160(dev.address),
        sc.ContractParam.integer(1),
        sc.ContractParam.any()
    ]
})

try {
    transaction.script = script
    console.log(transaction.serialize())
} catch (e) {
    console.error(e)

    /**
     * throw new Error(`num2hexstring expected a number but got ${typeof num} instead.`);
     *            ^
     * Error: num2hexstring expected a number but got undefined instead.
     */
}

let signers = [
    {
      account: dev.scriptHash,
      scopes: tx.WitnessScope.CalledByEntry,
    },
]

try {
    transaction.signers = signers
    console.log(transaction.serialize())
} catch (e) {
    console.error(e)

    /**
     * prop.map((p) => (typeof p === "string" ? p : p.serialize())).join(""));
     *                                                    ^
     * TypeError: p.serialize is not a function
     */
}
xie-yue commented 1 year ago

@EdgeDLT transaction.script should be a hex string transaction.script = u.HexString.fromHex(script)

transaction.signers cannot use SignerLike directly, map it to Signer should be work transaction.signers = signers.map(s => new tx.Signer(s));

or you can put your params into constructor, like

const transaction = new tx.Transaction({
    signers: signers,
    validUntilBlock: validUntilBlock,
    script: script,
    attributes: attributes,
  });
EdgeDLT commented 1 year ago

Ah thanks @xie-yue! I missed the fact that the constructor was handling those conversions in the linked example.