Manually setting ‘kind’ property required for transaction args
Closed this issue · 10 comments
Hi there, I am facing a problem passing address
types in my moveCalls through the typemove builder.
I generated the types for my package successfully, and I am trying to make a transaction for the following Move function.
Here is the move function signature on Sui:
public fun authorize_api(
self: &mut SharedObjectA,
pub: &Publisher,
addr: address,
_ctx: &mut TxContext,
) {}
and here is the generated type from typemove:
export function authorizeApi(
tx: Transaction,
args: [
string | TransactionObjectArgument | TransactionArgument,
string | TransactionObjectArgument | TransactionArgument,
string | TransactionArgument,
],
): TransactionArgument &
[TransactionArgument, TransactionArgument, TransactionArgument] {
const _args: any[] = [];
_args.push(transactionArgumentOrObject(args[0], tx));
_args.push(transactionArgumentOrObject(args[1], tx));
_args.push(transactionArgumentOrPure(args[2], tx));
// @ts-ignore
return tx.moveCall({
target:
"PACKAGE_ID::MODULE::authorize_api",
arguments: _args,
});
}
I constantly get InvalidBCSBytes
when executing the transaction through the typemove builder.
When I inspect the failed transaction on explorer, I see that Input 2 (which is the addr field) has type "pure", Value type "address", but the Value is 66,48,120,56,99,57,52,97,97,1...1,97,56,99,98,56
(66 bytes) instead of my actual address 0x2313..34234
.
My TS code looks like this when I construct the moveCall through the builder
export const authorizeApi = async (
client: SuiClient,
shared_object_id: string,
publisher_id: string,
targetAddress: string
) => {
const tx = new Transaction();
module.builder.authorizeApi(tx, [
shared_object_id,
publisher_id,
targetAddress,
]);
await client.signAndExecuteTransaction({...});
}
I tried passing targetAddress
as such as well:
tx.pure.address(targetAddress)
_0x2.address.builder.fromAsciiBytes(tx, [
targetAddress,
]);
But had no luck. When I execute the moveCall by the Sui SDK directly, everything is ok. The issue is this weird conversion of address to bytes - or maybe something else that I am failing to understand, that is causing the error: 'CommandArgumentError { arg_idx: 2, kind: InvalidBCSBytes } in command 0'
Here is a list of the versions I am using
"dependencies": {
"@mysten/sui": "^1.14.0",
"@typemove/move": "^1.6.6",
"@typemove/sui": "^1.6.6",
"@types/node": "^22.8.6",
"dotenv": "^16.4.5",
"env-cmd": "^10.1.0",
"ts-node": "^10.9.2",
"tslib": "^2.8.1",
"typescript": "^5.6.3"
}
would you also share the link in the explorer?
Here is an example on testnet.
I found a workaround for this, by defining the Kind
of the arg explicitly, and I had to use it for multiple args, and, of different types.
Here are some examples of my code and the places I had to use this hotfix, maybe it will help you fix it 🙏🏻
let addr = tx.pure.address(targetAddress);
addr["kind"] = "Input";
module.builder.authorizeApi(tx, [
tx.object(shared_object_id),
tx.object(publisher_id),
addr,
]);
const [custom_coin] = tx.splitCoins(tx.object(coin_id), [amount]);
custom_coin["kind"] = "Input";
module.builder.deposit(
tx,
[tx.object(safe_id), custom_coin, tx.object(publisher_id)],
[CUSTOM_COIN_TYPE]
);
// Specify input types for the transaction (typemove specific fix)
let userAddressArg = tx.pure.address(userAddress);
userAddressArg["kind"] = "Input";
let tokenValue = tx.pure.u64(BigInt(value));
tokenValue["kind"] = "Input";
let [config] = module.builder.initSend(tx, [registryId]);
config["kind"] = "Input";
module.builder.sendToken(
tx,
[
tx.object(safeId),
tokenValue,
userId,
userAddressArg,
tx.object(registryId),
config,
],
[CUSTOM_COIN_TYPE]
);
let addr = tx.pure.address(targetAddress); addr["kind"] = "Input"; module.builder.authorizeApi(tx, [ tx.object(shared_object_id), tx.object(publisher_id), addr, ]);
cut an new release v1.6.8-rc.1
but I have a question in your previous code?
do you really need, the error tx is when you directly pass pure string right?
addr["kind"] = "Input";
after you do tx.pure.address(targetAddress);
It would throw that error even if I passed targetAddress
directly in the params
How should I pass the args correctly with the new release? Because I updated to 1.6.8
and running this gives me SyntaxError: Cannot convert [object Object] to a BigInt
module.builder.authorizeApi(tx, [
tx.object(shared_object_id),
tx.object(publisher_id),
tx.pure.address(targetAddress),
]);
https://github.com/sentioxyz/typemove/blob/main/packages/sui/src/tests/move-call.test.ts#L44
in 1.6.8, I use devInspect to simulate the same tx and it works ok, but will try with the example you provided
it suppose to work like:
if it pass an tx argment, e.g. tx.object, then just use original object, if not, then try to wrap it with correct type
I tried to use view
instead of builder
as you did in the test, pass the args without tx declaration, and devInspect
does give me a VMVerificationOrDeserializationError in command 0
const res = await module.view.authorizeApi(client, [
shared_object_id,
publisher_id,
targetAddress,
]);
got it, will look deeper
Nevertheless, I believe we found the root issue that causes previous issue, try 1.6.11, use like this:
const arg = airdrop.builder.authorizeApi(tx, [
tx.object('0x080c14c97f457e8d40036109e647376beef62d3de35b51a3b9d183295fc8dc1c'),
tx.object('0x53a38614e77a540d037c3edea864d0fc5bbe8f5049230b6e1ce173f76596357f'),
tx.pure.address(SENDER)
])
```
or
const arg = airdrop.builder.authorizeApi(tx, [
'0x080c14c97f457e8d40036109e647376beef62d3de35b51a3b9d183295fc8dc1c',
'0x53a38614e77a540d037c3edea864d0fc5bbe8f5049230b6e1ce173f76596357f',
SENDER
])
```
or mixed
Yeap, it's good now! I used both ways that you suggested and no issue. Thank you!