Comparing version 1.13.1 to 1.13.2
@@ -7,2 +7,5 @@ # Aptos TS SDK Changelog | ||
## 1.13.2 (2023-07-12) | ||
- Add support for `Option<T>` and `vector<Object<T>>` in the SDK | ||
## 1.13.1 (2023-07-06) | ||
@@ -9,0 +12,0 @@ |
@@ -88,3 +88,3 @@ { | ||
}, | ||
"version": "1.13.1" | ||
"version": "1.13.2" | ||
} |
@@ -22,2 +22,4 @@ // Copyright © Aptos Foundation | ||
return TransactionAuthenticatorMultiAgent.load(deserializer); | ||
case 3: | ||
return TransactionAuthenticatorFeePayer.load(deserializer); | ||
default: | ||
@@ -104,2 +106,32 @@ throw new Error(`Unknown variant index for TransactionAuthenticator: ${index}`); | ||
export class TransactionAuthenticatorFeePayer extends TransactionAuthenticator { | ||
constructor( | ||
public readonly sender: AccountAuthenticator, | ||
public readonly secondary_signer_addresses: Seq<AccountAddress>, | ||
public readonly secondary_signers: Seq<AccountAuthenticator>, | ||
public readonly fee_payer: { address: AccountAddress; authenticator: AccountAuthenticator }, | ||
) { | ||
super(); | ||
} | ||
serialize(serializer: Serializer): void { | ||
serializer.serializeU32AsUleb128(3); | ||
this.sender.serialize(serializer); | ||
serializeVector<AccountAddress>(this.secondary_signer_addresses, serializer); | ||
serializeVector<AccountAuthenticator>(this.secondary_signers, serializer); | ||
this.fee_payer.address.serialize(serializer); | ||
this.fee_payer.authenticator.serialize(serializer); | ||
} | ||
static load(deserializer: Deserializer): TransactionAuthenticatorMultiAgent { | ||
const sender = AccountAuthenticator.deserialize(deserializer); | ||
const secondary_signer_addresses = deserializeVector(deserializer, AccountAddress); | ||
const secondary_signers = deserializeVector(deserializer, AccountAuthenticator); | ||
const address = AccountAddress.deserialize(deserializer); | ||
const authenticator = AccountAuthenticator.deserialize(deserializer); | ||
const fee_payer = { address, authenticator }; | ||
return new TransactionAuthenticatorFeePayer(sender, secondary_signer_addresses, secondary_signers, fee_payer); | ||
} | ||
} | ||
export abstract class AccountAuthenticator { | ||
@@ -106,0 +138,0 @@ abstract serialize(serializer: Serializer): void; |
@@ -24,3 +24,3 @@ // Copyright © Aptos Foundation | ||
} from "../bcs"; | ||
import { TransactionAuthenticator } from "./authenticator"; | ||
import { AccountAuthenticator, TransactionAuthenticator, TransactionAuthenticatorMultiAgent } from "./authenticator"; | ||
import { Identifier } from "./identifier"; | ||
@@ -375,2 +375,4 @@ import { TypeTag } from "./type_tag"; | ||
return MultiAgentRawTransaction.load(deserializer); | ||
case 1: | ||
return FeePayerRawTransaction.load(deserializer); | ||
default: | ||
@@ -405,2 +407,28 @@ throw new Error(`Unknown variant index for RawTransactionWithData: ${index}`); | ||
export class FeePayerRawTransaction extends RawTransactionWithData { | ||
constructor( | ||
public readonly raw_txn: RawTransaction, | ||
public readonly secondary_signer_addresses: Seq<AccountAddress>, | ||
public readonly fee_payer_address: AccountAddress, | ||
) { | ||
super(); | ||
} | ||
serialize(serializer: Serializer): void { | ||
// enum variant index | ||
serializer.serializeU32AsUleb128(1); | ||
this.raw_txn.serialize(serializer); | ||
serializeVector<TransactionArgument>(this.secondary_signer_addresses, serializer); | ||
this.fee_payer_address.serialize(serializer); | ||
} | ||
static load(deserializer: Deserializer): FeePayerRawTransaction { | ||
const rawTxn = RawTransaction.deserialize(deserializer); | ||
const secondarySignerAddresses = deserializeVector(deserializer, AccountAddress); | ||
const feePayerAddress = AccountAddress.deserialize(deserializer); | ||
return new FeePayerRawTransaction(rawTxn, secondarySignerAddresses, feePayerAddress); | ||
} | ||
} | ||
export abstract class TransactionPayload { | ||
@@ -407,0 +435,0 @@ abstract serialize(serializer: Serializer): void; |
@@ -228,2 +228,10 @@ // Copyright © Aptos Foundation | ||
export function optionStructTag(typeArg: TypeTag): StructTag { | ||
return new StructTag(AccountAddress.fromHex("0x1"), new Identifier("option"), new Identifier("Option"), [typeArg]); | ||
} | ||
export function objectStructTag(typeArg: TypeTag): StructTag { | ||
return new StructTag(AccountAddress.fromHex("0x1"), new Identifier("object"), new Identifier("Object"), [typeArg]); | ||
} | ||
function bail(message: string) { | ||
@@ -230,0 +238,0 @@ throw new TypeTagParserError(message); |
@@ -294,8 +294,8 @@ // Copyright © Aptos Foundation | ||
* | ||
* @param sender AptosAccount where token from which tokens will be transfered | ||
* @param receiver Hex-encoded 32 byte Aptos account address to which tokens will be transfered | ||
* @param sender AptosAccount where token from which tokens will be transferred | ||
* @param receiver Hex-encoded 32 byte Aptos account address to which tokens will be transferred | ||
* @param creator Hex-encoded 32 byte Aptos account address to which created tokens | ||
* @param collectionName Name of collection where token is stored | ||
* @param name Token name | ||
* @param amount Amount of tokens which will be transfered | ||
* @param amount Amount of tokens which will be transferred | ||
* @param property_version the version of token PropertyMap with a default value 0. | ||
@@ -357,2 +357,81 @@ * @returns The hash of the transaction submitted to the API | ||
/** | ||
* Directly transfer the specified amount of tokens from account to receiver | ||
* using a single multi signature transaction. | ||
* | ||
* @param sender AptosAccount where token from which tokens will be transferred | ||
* @param receiver Hex-encoded 32 byte Aptos account address to which tokens will be transferred | ||
* @param creator Hex-encoded 32 byte Aptos account address to which created tokens | ||
* @param collectionName Name of collection where token is stored | ||
* @param name Token name | ||
* @param amount Amount of tokens which will be transferred | ||
* @param fee_payer AptosAccount which will pay fee for transaction | ||
* @param property_version the version of token PropertyMap with a default value 0. | ||
* @returns The hash of the transaction submitted to the API | ||
*/ | ||
async directTransferTokenWithFeePayer( | ||
sender: AptosAccount, | ||
receiver: AptosAccount, | ||
creator: MaybeHexString, | ||
collectionName: string, | ||
name: string, | ||
amount: AnyNumber, | ||
fee_payer: AptosAccount, | ||
propertyVersion: AnyNumber = 0, | ||
extraArgs?: OptionalTransactionArgs, | ||
): Promise<string> { | ||
const builder = new TransactionBuilderRemoteABI(this.aptosClient, { sender: sender.address(), ...extraArgs }); | ||
const rawTxn = await builder.build( | ||
"0x3::token::direct_transfer_script", | ||
[], | ||
[creator, collectionName, name, propertyVersion, amount], | ||
); | ||
const feePayerTxn = new TxnBuilderTypes.FeePayerRawTransaction( | ||
rawTxn, | ||
[TxnBuilderTypes.AccountAddress.fromHex(receiver.address())], | ||
TxnBuilderTypes.AccountAddress.fromHex(fee_payer.address()), | ||
); | ||
const senderSignature = new TxnBuilderTypes.Ed25519Signature( | ||
sender.signBuffer(TransactionBuilder.getSigningMessage(feePayerTxn)).toUint8Array(), | ||
); | ||
const senderAuthenticator = new TxnBuilderTypes.AccountAuthenticatorEd25519( | ||
new TxnBuilderTypes.Ed25519PublicKey(sender.signingKey.publicKey), | ||
senderSignature, | ||
); | ||
const receiverSignature = new TxnBuilderTypes.Ed25519Signature( | ||
receiver.signBuffer(TransactionBuilder.getSigningMessage(feePayerTxn)).toUint8Array(), | ||
); | ||
const receiverAuthenticator = new TxnBuilderTypes.AccountAuthenticatorEd25519( | ||
new TxnBuilderTypes.Ed25519PublicKey(receiver.signingKey.publicKey), | ||
receiverSignature, | ||
); | ||
const feePayerSignature = new TxnBuilderTypes.Ed25519Signature( | ||
fee_payer.signBuffer(TransactionBuilder.getSigningMessage(feePayerTxn)).toUint8Array(), | ||
); | ||
const feePayerAuthenticator = new TxnBuilderTypes.AccountAuthenticatorEd25519( | ||
new TxnBuilderTypes.Ed25519PublicKey(fee_payer.signingKey.publicKey), | ||
feePayerSignature, | ||
); | ||
const txAuthenticatorFeePayer = new TxnBuilderTypes.TransactionAuthenticatorFeePayer( | ||
senderAuthenticator, | ||
[TxnBuilderTypes.AccountAddress.fromHex(receiver.address())], | ||
[receiverAuthenticator], | ||
{ address: TxnBuilderTypes.AccountAddress.fromHex(fee_payer.address()), authenticator: feePayerAuthenticator }, | ||
); | ||
const bcsTxn = bcsToBytes(new TxnBuilderTypes.SignedTransaction(rawTxn, txAuthenticatorFeePayer)); | ||
const transactionRes = await this.aptosClient.submitSignedBCSTransaction(bcsTxn); | ||
return transactionRes.hash; | ||
} | ||
/** | ||
* User opt-in or out direct transfer through a boolean flag | ||
@@ -359,0 +438,0 @@ * |
@@ -464,42 +464,105 @@ // Copyright © Aptos Foundation | ||
); | ||
/* | ||
TODO(xinding): Skip test for now, as it's blocking CI | ||
test( | ||
"publishes a package", | ||
"submits multiagent transaction with fee payer", | ||
async () => { | ||
const client = new AptosClient(NODE_URL); | ||
const faucetClient = getFaucetClient(); | ||
const tokenClient = new TokenClient(client); | ||
const account1 = new AptosAccount( | ||
new HexString("0x883fdd67576e5fdceb370ba665b8af8856d0cae63fd808b8d16077c6b008ea8c").toUint8Array(), | ||
const alice = new AptosAccount(); | ||
const bob = new AptosAccount(); | ||
// Fund both Alice's and Bob's Account | ||
await faucetClient.fundAccount(alice.address(), 100000000); | ||
await faucetClient.fundAccount(bob.address(), 100000000); | ||
const collectionName = "AliceCollection"; | ||
const tokenName = "Alice Token"; | ||
async function ensureTxnSuccess(txnHashPromise: Promise<string>) { | ||
const txnHash = await txnHashPromise; | ||
const txn = await client.waitForTransactionWithResult(txnHash); | ||
expect((txn as any)?.success).toBe(true); | ||
} | ||
// Create collection and token on Alice's account | ||
await ensureTxnSuccess( | ||
tokenClient.createCollection(alice, collectionName, "Alice's simple collection", "https://aptos.dev"), | ||
); | ||
await faucetClient.fundAccount(account1.address(), 100_000_000); | ||
const txnHash = await client.publishPackage( | ||
account1, | ||
new HexString( | ||
// eslint-disable-next-line max-len | ||
"084578616d706c657301000000000000000040314137344146383742383132393043323533323938383036373846304137444637393737373637383734334431434345443230413446354345334238464446388f011f8b08000000000002ff3dccc10ac2300c06e07b9ea2f46ee70b78f0a02f31c6886d74a55d5b1a51417c7713c1915c927cf9c7863ee18d2628b89239187b7ae1da32b18507758eb5e872efa42cc088217462269e60a19ceb7cc9d527bf60fcb9594da0462550f151d9b1dd2b9fbba43f6b4f82de465e302b776e90befe8f03aadd6db3351ff802f2294cdfa100000001076d6573736167658f051f8b08000000000002ff95555d6bdb30147dcfafb8ed20d8c52c1d8c3194a6ec83b0be747be8dec6108a7d9d983a5226c94dc3f07f9f2cd98e6cc769e787884857e79e73bfb4154991236c30cf055de5227e8c372ce3846c5129b646f83b01f3150a41e984109452c879774f656b8e834d2d33be3e6eb29d168aa6926d712fe423212c8e45c175dfc27979c2ea64329b910b722b518942c6682d0d6e116bb877f4ee449ea0840d53f088879a6cf5d5f409381e843cd835ea1b5023979bc57a5404ec4ac8b25aee184f72bca95d7db586f6e0d6c19486df8d21d8f23b41d0bb65592652ec226323247a6c5329b6f445ca5a9cb7291d81d96c063f37681c640ab86894c2cef03434ac4d2cb8d2b0fcfe83de2f1f1e3e7f5b12283ebc87055ccf1dc8ae58e5590c69c1618dbaf11bb0249104aa5fb311f669008bff149939eaa5e728942985525f04f89c29ad6e3a66b7163d8cc0d618215c689a9a1249028f6718ce5bb0abe94a18d33d5de762c5f293686f6be67e806a6d2616f260152a5fa12b4b23cd5675345649a1857a51708e1a6a485a11322176c0a6015c14a94883696de289cb52082e46c2e4e185a1e7ccd6b57842aa450b198d52eb75423476d06f91264284e3de6dd2cd68a71ca575f1cbb0fd5b02e60a7bc4aab819c24d5ae8c6b15f4027e5745be8b3d1990f40fd56337057d3a197a666ba97ebc980db4c3bd5c1d47887f1ebddb845a726c230193ebd6146fc09108bdde174eeca9eec718a260003ada5df2a6f7e6954ba89a931ff74fdfc2efc3dd646dc60d398717aa6a3c25736cdff34cbd8e342482c9169a44d51a44252a7a85b1d27f846d0767ca1d38fc1eaf2ae7a2423f8d2be9297d5341acc362ff6fdd119c262f10a543f9ddeec6b776be2e5a49cfc0325c63f11c007000000000300000000000000000000000000000000000000000000000000000000000000010e4170746f734672616d65776f726b00000000000000000000000000000000000000000000000000000000000000010b4170746f735374646c696200000000000000000000000000000000000000000000000000000000000000010a4d6f76655374646c696200", | ||
).toUint8Array(), | ||
[ | ||
new TxnBuilderTypes.Module( | ||
new HexString( | ||
// eslint-disable-next-line max-len | ||
"a11ceb0b050000000c01000c020c12031e20043e04054228076ad50108bf024006ff020a108903450ace03150ce3035f0dc20404000001010102010301040105000606000007080005080700030e040106010009000100000a020300020f0404000410060000011106080106031209030106040705070105010802020c08020001030305080207080101060c010800010b0301090002070b030109000900076d657373616765076163636f756e74056572726f72056576656e74067369676e657206737472696e67124d6573736167654368616e67654576656e740d4d657373616765486f6c64657206537472696e670b6765745f6d6573736167650b7365745f6d6573736167650c66726f6d5f6d6573736167650a746f5f6d657373616765156d6573736167655f6368616e67655f6576656e74730b4576656e7448616e646c65096e6f745f666f756e640a616464726573735f6f66106e65775f6576656e745f68616e646c650a656d69745f6576656e746766284c3984add58e00d20ba272a40d33d5b4ea33c08a904254e28fdff97b9f000000000000000000000000000000000000000000000000000000000000000103080000000000000000126170746f733a3a6d657461646174615f7630310100000000000000000b454e4f5f4d4553534147451b5468657265206973206e6f206d6573736167652070726573656e740002020b08020c08020102020008020d0b030108000001000101030b0a002901030607001102270b002b0110001402010104010105210e0011030c020a022901200308050f0e000b010e00380012012d0105200b022a010c040a041000140c030a040f010b030a01120038010b010b040f0015020100010100", | ||
).toUint8Array(), | ||
), | ||
], | ||
await ensureTxnSuccess( | ||
tokenClient.createToken( | ||
alice, | ||
collectionName, | ||
tokenName, | ||
"Alice's simple token", | ||
1, | ||
"https://aptos.dev/img/nyan.jpeg", | ||
1000, | ||
alice.address(), | ||
0, | ||
0, | ||
["key"], | ||
["2"], | ||
["u64"], | ||
), | ||
); | ||
await client.waitForTransaction(txnHash); | ||
const propertyVersion = 0; | ||
const tokenId = { | ||
token_data_id: { | ||
creator: alice.address().hex(), | ||
collection: collectionName, | ||
name: tokenName, | ||
}, | ||
property_version: `${propertyVersion}`, | ||
}; | ||
const txn = await client.getTransactionByHash(txnHash); | ||
expect((txn as any).success).toBeTruthy(); | ||
// Transfer Token from Alice's Account to Bob's Account with bob paying the fee | ||
await tokenClient.getCollectionData(alice.address().hex(), collectionName); | ||
let aliceBalance = await tokenClient.getTokenForAccount(alice.address().hex(), tokenId); | ||
expect(aliceBalance.amount).toBe("1"); | ||
const getBalance = async (account: AptosAccount) => { | ||
const resources = await client.getAccountResources(account.address().hex()); | ||
let accountResource = resources.find((r) => r.type === aptosCoin); | ||
return BigInt((accountResource!.data as any).coin.value); | ||
}; | ||
const aliceBefore = await getBalance(alice); | ||
const bobBefore = await getBalance(bob); | ||
const txnHash = await tokenClient.directTransferTokenWithFeePayer( | ||
alice, | ||
bob, | ||
alice.address(), | ||
collectionName, | ||
tokenName, | ||
1, | ||
bob, | ||
propertyVersion, | ||
undefined, | ||
); | ||
await client.waitForTransaction(txnHash, { checkSuccess: true }); | ||
aliceBalance = await tokenClient.getTokenForAccount(alice.address().hex(), tokenId); | ||
expect(aliceBalance.amount).toBe("0"); | ||
const bobBalance = await tokenClient.getTokenForAccount(bob.address().hex(), tokenId); | ||
expect(bobBalance.amount).toBe("1"); | ||
// Check that Alice did not pay the fee | ||
expect(await getBalance(alice)).toBe(aliceBefore); | ||
// Check that Bob paid the fee | ||
expect(await getBalance(bob)).toBeLessThan(bobBefore); | ||
}, | ||
longTestTimeout, | ||
); | ||
*/ | ||
/* | ||
TODO(gnazario): Skip test for now, as it's blocking CI | ||
test( | ||
"create resource account and publish a package", | ||
"publishes a package", | ||
async () => { | ||
@@ -513,7 +576,5 @@ const client = new AptosClient(NODE_URL); | ||
await faucetClient.fundAccount(account1.address(), 100_000_000); | ||
const seed = "3030"; | ||
const txnHash = await client.createResourceAccountAndPublishPackage( | ||
const txnHash = await client.publishPackage( | ||
account1, | ||
new TextEncoder().encode(seed), | ||
new HexString( | ||
@@ -533,7 +594,9 @@ // eslint-disable-next-line max-len | ||
await client.waitForTransaction(txnHash, { checkSuccess: true }); | ||
await client.waitForTransaction(txnHash); | ||
const txn = await client.getTransactionByHash(txnHash); | ||
expect((txn as any).success).toBeTruthy(); | ||
}, | ||
longTestTimeout, | ||
); | ||
*/ | ||
@@ -540,0 +603,0 @@ test( |
@@ -8,2 +8,4 @@ // Copyright © Aptos Foundation | ||
Identifier, | ||
objectStructTag, | ||
optionStructTag, | ||
StructTag, | ||
@@ -36,2 +38,3 @@ TransactionArgumentAddress, | ||
} from "../../transaction_builder/builder_utils"; | ||
import { stringStructTag } from "../../aptos_types/type_tag"; | ||
@@ -81,3 +84,3 @@ describe("BuilderUtils", () => { | ||
it("parses a sturct TypeTag", async () => { | ||
it("parses a struct TypeTag", async () => { | ||
const assertStruct = (struct: TypeTagStruct, accountAddress: string, moduleName: string, structName: string) => { | ||
@@ -172,3 +175,6 @@ expect(HexString.fromUint8Array(struct.value.address.address).toShortString()).toBe(accountAddress); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x01])); | ||
serializer = new Serializer(); | ||
}); | ||
it("throws on serializing an invalid boolean arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -183,4 +189,6 @@ serializeArg(123, new TypeTagBool(), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0xff])); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws on serializing an invalid u8 arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -195,4 +203,6 @@ serializeArg("u8", new TypeTagU8(), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0xff, 0x7f])); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws on serializing an invalid u16 arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -207,4 +217,6 @@ serializeArg("u16", new TypeTagU16(), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x04, 0x03, 0x02, 0x01])); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws on serializing an invalid u32 arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -219,4 +231,6 @@ serializeArg("u32", new TypeTagU32(), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws on serializing an invalid u64 arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -233,4 +247,6 @@ serializeArg("u64", new TypeTagU64(), serializer); | ||
); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws on serializing an invalid u128 arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -254,4 +270,6 @@ serializeArg("u128", new TypeTagU128(), serializer); | ||
); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws on serializing an invalid u256 arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -268,6 +286,12 @@ serializeArg("u256", new TypeTagU256(), serializer); | ||
serializer = new Serializer(); | ||
serializeArg(HexString.ensure("0x1"), new TypeTagAddress(), serializer); | ||
expect(HexString.fromUint8Array(serializer.getBytes()).toShortString()).toEqual("0x1"); | ||
serializer = new Serializer(); | ||
serializeArg(AccountAddress.fromHex("0x1"), new TypeTagAddress(), serializer); | ||
expect(HexString.fromUint8Array(serializer.getBytes()).toShortString()).toEqual("0x1"); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws on serializing an invalid AccountAddress arg", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -282,12 +306,35 @@ serializeArg(123456, new TypeTagAddress(), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x1, 0xff])); | ||
}); | ||
serializer = new Serializer(); | ||
it("serializes a vector u8 arg from string characters", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg("abc", new TypeTagVector(new TypeTagU8()), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x61, 0x62, 0x63])); | ||
}); | ||
serializer = new Serializer(); | ||
it("serializes a vector u8 arg from a hex string", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg(HexString.ensure("0x010203"), new TypeTagVector(new TypeTagU8()), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x01, 0x02, 0x03])); | ||
}); | ||
it("serializes a vector u8 arg from a uint8array", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg(new Uint8Array([0x61, 0x62, 0x63]), new TypeTagVector(new TypeTagU8()), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x61, 0x62, 0x63])); | ||
}); | ||
serializer = new Serializer(); | ||
it("serializes a vector of Objects", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg(["0xbeef"], new TypeTagVector(new TypeTagStruct(objectStructTag(new TypeTagU8()))), serializer); | ||
expect(serializer.getBytes()).toEqual( | ||
new Uint8Array([ | ||
0x1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, | ||
]), | ||
); | ||
}); | ||
it("throws error when serializing a mismatched type", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -298,14 +345,44 @@ serializeArg(123456, new TypeTagVector(new TypeTagU8()), serializer); | ||
it("serializes a struct arg", async () => { | ||
it("serializes a string arg", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg("abc", new TypeTagStruct(stringStructTag), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x61, 0x62, 0x63])); | ||
}); | ||
it("serializes an empty option arg", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg(undefined, new TypeTagStruct(optionStructTag(new TypeTagU8())), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x0])); | ||
}); | ||
it("serializes an option num arg", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg("1", new TypeTagStruct(optionStructTag(new TypeTagU8())), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x1, 0x1])); | ||
}); | ||
it("serializes an option string arg", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg("abc", new TypeTagStruct(optionStructTag(new TypeTagStruct(stringStructTag))), serializer); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x1, 0x3, 0x61, 0x62, 0x63])); | ||
}); | ||
it("serializes a optional Object", async () => { | ||
let serializer = new Serializer(); | ||
serializeArg( | ||
"abc", | ||
new TypeTagStruct( | ||
new StructTag(AccountAddress.fromHex("0x1"), new Identifier("string"), new Identifier("String"), []), | ||
), | ||
"0x01", | ||
new TypeTagStruct(optionStructTag(new TypeTagStruct(objectStructTag(new TypeTagU8())))), | ||
serializer, | ||
); | ||
expect(serializer.getBytes()).toEqual(new Uint8Array([0x3, 0x61, 0x62, 0x63])); | ||
//00 00 00 00 00000000 00000000 00000000 00000000 00000000 00000000 00000000 | ||
expect(serializer.getBytes()).toEqual( | ||
new Uint8Array([ | ||
0x1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, | ||
]), | ||
); | ||
}); | ||
serializer = new Serializer(); | ||
it("throws when unsupported struct type", async () => { | ||
let serializer = new Serializer(); | ||
expect(() => { | ||
@@ -319,3 +396,3 @@ serializeArg( | ||
); | ||
}).toThrow("The only supported struct arg is of type 0x1::string::String"); | ||
}).toThrow("Unsupported struct type in function argument"); | ||
}); | ||
@@ -322,0 +399,0 @@ |
import { | ||
objectStructTag, | ||
StructTag, | ||
@@ -110,2 +111,14 @@ TypeTag, | ||
test("TypeTagParser successfully parses an Option type", () => { | ||
const typeTag = "0x1::option::Option<u8>"; | ||
const parser = new TypeTagParser(typeTag); | ||
const result = parser.parseTypeTag(); | ||
if (result instanceof TypeTagStruct) { | ||
expect(result.value === objectStructTag(new TypeTagU8())); | ||
} else { | ||
fail(`Not an option ${result}`); | ||
} | ||
}); | ||
test("TypeTagParser successfully parses a strcut with a nested Object type", () => { | ||
@@ -112,0 +125,0 @@ const typeTag = "0x1::some_module::SomeResource<0x1::object::Object<T>>"; |
@@ -75,82 +75,102 @@ // Copyright © Aptos Foundation | ||
export function serializeArg(argVal: any, argType: TypeTag, serializer: Serializer) { | ||
serializeArgInner(argVal, argType, serializer, 0); | ||
} | ||
function serializeArgInner(argVal: any, argType: TypeTag, serializer: Serializer, depth: number) { | ||
if (argType instanceof TypeTagBool) { | ||
serializer.serializeBool(ensureBoolean(argVal)); | ||
return; | ||
} | ||
if (argType instanceof TypeTagU8) { | ||
} else if (argType instanceof TypeTagU8) { | ||
serializer.serializeU8(ensureNumber(argVal)); | ||
return; | ||
} | ||
if (argType instanceof TypeTagU16) { | ||
} else if (argType instanceof TypeTagU16) { | ||
serializer.serializeU16(ensureNumber(argVal)); | ||
return; | ||
} | ||
if (argType instanceof TypeTagU32) { | ||
} else if (argType instanceof TypeTagU32) { | ||
serializer.serializeU32(ensureNumber(argVal)); | ||
return; | ||
} | ||
if (argType instanceof TypeTagU64) { | ||
} else if (argType instanceof TypeTagU64) { | ||
serializer.serializeU64(ensureBigInt(argVal)); | ||
return; | ||
} | ||
if (argType instanceof TypeTagU128) { | ||
} else if (argType instanceof TypeTagU128) { | ||
serializer.serializeU128(ensureBigInt(argVal)); | ||
return; | ||
} | ||
if (argType instanceof TypeTagU256) { | ||
} else if (argType instanceof TypeTagU256) { | ||
serializer.serializeU256(ensureBigInt(argVal)); | ||
return; | ||
} else if (argType instanceof TypeTagAddress) { | ||
serializeAddress(argVal, serializer); | ||
} else if (argType instanceof TypeTagVector) { | ||
serializeVector(argVal, argType, serializer, depth); | ||
} else if (argType instanceof TypeTagStruct) { | ||
serializeStruct(argVal, argType, serializer, depth); | ||
} else { | ||
throw new Error("Unsupported arg type."); | ||
} | ||
if (argType instanceof TypeTagAddress) { | ||
let addr: AccountAddress; | ||
if (typeof argVal === "string" || argVal instanceof HexString) { | ||
addr = AccountAddress.fromHex(argVal); | ||
} else if (argVal instanceof AccountAddress) { | ||
addr = argVal; | ||
} else { | ||
throw new Error("Invalid account address."); | ||
} | ||
addr.serialize(serializer); | ||
return; | ||
} | ||
function serializeAddress(argVal: any, serializer: Serializer) { | ||
let addr: AccountAddress; | ||
if (typeof argVal === "string" || argVal instanceof HexString) { | ||
addr = AccountAddress.fromHex(argVal); | ||
} else if (argVal instanceof AccountAddress) { | ||
addr = argVal; | ||
} else { | ||
throw new Error("Invalid account address."); | ||
} | ||
if (argType instanceof TypeTagVector) { | ||
// We are serializing a vector<u8> | ||
if (argType.value instanceof TypeTagU8) { | ||
if (argVal instanceof Uint8Array) { | ||
serializer.serializeBytes(argVal); | ||
return; | ||
} | ||
addr.serialize(serializer); | ||
} | ||
if (typeof argVal === "string") { | ||
serializer.serializeStr(argVal); | ||
return; | ||
} | ||
function serializeVector(argVal: any, argType: TypeTagVector, serializer: Serializer, depth: number) { | ||
// We are serializing a vector<u8> | ||
if (argType.value instanceof TypeTagU8) { | ||
if (argVal instanceof Uint8Array) { | ||
serializer.serializeBytes(argVal); | ||
return; | ||
} | ||
if (!Array.isArray(argVal)) { | ||
throw new Error("Invalid vector args."); | ||
if (argVal instanceof HexString) { | ||
serializer.serializeBytes(argVal.toUint8Array()); | ||
return; | ||
} | ||
if (typeof argVal === "string") { | ||
serializer.serializeStr(argVal); | ||
return; | ||
} | ||
// If it isn't any of those types, then it must just be an actual array of numbers | ||
} | ||
serializer.serializeU32AsUleb128(argVal.length); | ||
argVal.forEach((arg) => serializeArg(arg, argType.value, serializer)); | ||
return; | ||
if (!Array.isArray(argVal)) { | ||
throw new Error("Invalid vector args."); | ||
} | ||
if (argType instanceof TypeTagStruct) { | ||
const { address, module_name: moduleName, name } = (argType as TypeTagStruct).value; | ||
if ( | ||
`${HexString.fromUint8Array(address.address).toShortString()}::${moduleName.value}::${name.value}` !== | ||
"0x1::string::String" | ||
) { | ||
throw new Error("The only supported struct arg is of type 0x1::string::String"); | ||
} | ||
serializer.serializeU32AsUleb128(argVal.length); | ||
argVal.forEach((arg) => serializeArgInner(arg, argType.value, serializer, depth + 1)); | ||
} | ||
function serializeStruct(argVal: any, argType: TypeTag, serializer: Serializer, depth: number) { | ||
const { address, module_name: moduleName, name, type_args: typeArgs } = (argType as TypeTagStruct).value; | ||
const structType = `${HexString.fromUint8Array(address.address).toShortString()}::${moduleName.value}::${name.value}`; | ||
if (structType === "0x1::string::String") { | ||
assertType(argVal, ["string"]); | ||
serializer.serializeStr(argVal); | ||
return; | ||
} else if (structType === "0x1::object::Object") { | ||
serializeAddress(argVal, serializer); | ||
} else if (structType === "0x1::option::Option") { | ||
if (typeArgs.length !== 1) { | ||
throw new Error(`Option has the wrong number of type arguments ${typeArgs.length}`); | ||
} | ||
serializeOption(argVal, typeArgs[0], serializer, depth); | ||
} else { | ||
throw new Error("Unsupported struct type in function argument"); | ||
} | ||
throw new Error("Unsupported arg type."); | ||
} | ||
function serializeOption(argVal: any, argType: TypeTag, serializer: Serializer, depth: number) { | ||
// For option, we determine if it's empty or not empty first | ||
// empty option is nothing, we specifically check for undefined to prevent fuzzy matching | ||
if (argVal === undefined) { | ||
serializer.serializeU32AsUleb128(0); | ||
} else { | ||
// Something means we need an array of 1 | ||
serializer.serializeU32AsUleb128(1); | ||
// Serialize the inner type arg, ensuring that depth is tracked | ||
serializeArgInner(argVal, argType, serializer, depth + 1); | ||
} | ||
} | ||
export function argToTransactionArgument(argVal: any, argType: TypeTag): TransactionArgument { | ||
@@ -157,0 +177,0 @@ if (argType instanceof TypeTagBool) { |
@@ -16,2 +16,3 @@ // Copyright © Aptos Foundation | ||
MultiAgentRawTransaction, | ||
FeePayerRawTransaction, | ||
AccountAddress, | ||
@@ -46,3 +47,3 @@ EntryFunction, | ||
type AnyRawTransaction = RawTransaction | MultiAgentRawTransaction; | ||
type AnyRawTransaction = RawTransaction | MultiAgentRawTransaction | FeePayerRawTransaction; | ||
@@ -83,2 +84,4 @@ /** | ||
hash.update(RAW_TRANSACTION_WITH_DATA_SALT); | ||
} else if (rawTxn instanceof FeePayerRawTransaction) { | ||
hash.update(RAW_TRANSACTION_WITH_DATA_SALT); | ||
} else { | ||
@@ -85,0 +88,0 @@ throw new Error("Unknown transaction type."); |
// hardcoded for now, we would want to have it injected dynamically | ||
export const VERSION = "1.13.1"; | ||
export const VERSION = "1.13.2"; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
3218380
35105