@mysten/sui 2.30.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/bcs/bcs.d.mts +6 -6
- package/dist/bcs/bcs.d.mts.map +1 -1
- package/dist/bcs/bcs.mjs +5 -1
- package/dist/bcs/bcs.mjs.map +1 -1
- package/dist/bcs/index.d.mts +103 -11
- package/dist/bcs/index.d.mts.map +1 -1
- package/dist/bcs/types.d.mts.map +1 -1
- package/dist/client/core-resolver.mjs +2 -1
- package/dist/client/core-resolver.mjs.map +1 -1
- package/dist/client/transaction-resolver.mjs +35 -8
- package/dist/client/transaction-resolver.mjs.map +1 -1
- package/dist/cryptography/signature.d.mts +6 -6
- package/dist/graphql/generated/tada-env.d.mts +74 -0
- package/dist/grpc/proto/sui/rpc/v2/input.d.mts +21 -1
- package/dist/grpc/proto/sui/rpc/v2/input.d.mts.map +1 -1
- package/dist/grpc/proto/sui/rpc/v2/input.mjs +21 -0
- package/dist/grpc/proto/sui/rpc/v2/input.mjs.map +1 -1
- package/dist/grpc/proto/sui/rpc/v2/ledger_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/move_package_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/name_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/subscription_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.client.d.mts +4 -4
- package/dist/jsonRpc/core.mjs +1 -1
- package/dist/jsonRpc/core.mjs.map +1 -1
- package/dist/transactions/Transaction.d.mts +44 -39
- package/dist/transactions/Transaction.d.mts.map +1 -1
- package/dist/transactions/Transaction.mjs +65 -24
- package/dist/transactions/Transaction.mjs.map +1 -1
- package/dist/transactions/data/internal.d.mts +12 -0
- package/dist/transactions/data/internal.d.mts.map +1 -1
- package/dist/transactions/data/internal.mjs +5 -1
- package/dist/transactions/data/internal.mjs.map +1 -1
- package/dist/transactions/data/v2.d.mts +5 -0
- package/dist/transactions/data/v2.d.mts.map +1 -1
- package/dist/transactions/index.d.mts +3 -2
- package/dist/transactions/intents/AllowanceBalance.mjs +147 -0
- package/dist/transactions/intents/AllowanceBalance.mjs.map +1 -0
- package/dist/transactions/intents/BalanceIntentNames.mjs +7 -0
- package/dist/transactions/intents/BalanceIntentNames.mjs.map +1 -0
- package/dist/transactions/intents/BalanceOptions.d.mts +27 -0
- package/dist/transactions/intents/BalanceOptions.d.mts.map +1 -0
- package/dist/transactions/intents/BalanceOptions.mjs +12 -0
- package/dist/transactions/intents/BalanceOptions.mjs.map +1 -0
- package/dist/transactions/intents/CoinWithBalance.d.mts.map +1 -1
- package/dist/transactions/intents/CoinWithBalance.mjs +31 -10
- package/dist/transactions/intents/CoinWithBalance.mjs.map +1 -1
- package/dist/transactions/intents/ResolveBalances.mjs +16 -0
- package/dist/transactions/intents/ResolveBalances.mjs.map +1 -0
- package/dist/transactions/resolve.d.mts.map +1 -1
- package/dist/transactions/resolve.mjs +1 -1
- package/dist/transactions/resolve.mjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/version.mjs.map +1 -1
- package/dist/zklogin/bcs.d.mts +14 -14
- package/docs/llms-index.md +1 -0
- package/docs/transactions/allowances.md +176 -0
- package/docs/transactions/coins-and-balances.md +12 -9
- package/package.json +1 -1
- package/src/bcs/bcs.ts +4 -0
- package/src/bcs/types.ts +2 -1
- package/src/client/core-resolver.ts +6 -4
- package/src/client/transaction-resolver.ts +43 -9
- package/src/graphql/generated/schema.graphql +87 -42
- package/src/graphql/generated/tada-env.ts +84 -0
- package/src/grpc/proto/sui/rpc/v2/input.ts +22 -0
- package/src/jsonRpc/core.ts +3 -4
- package/src/transactions/Transaction.ts +70 -49
- package/src/transactions/data/internal.ts +4 -0
- package/src/transactions/index.ts +3 -0
- package/src/transactions/intents/AllowanceBalance.ts +204 -0
- package/src/transactions/intents/BalanceIntentNames.ts +5 -0
- package/src/transactions/intents/BalanceOptions.ts +45 -0
- package/src/transactions/intents/CoinWithBalance.ts +51 -8
- package/src/transactions/intents/ResolveBalances.ts +30 -0
- package/src/transactions/resolve.ts +6 -0
- package/src/version.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.mjs","names":[],"sources":["../../../src/transactions/data/internal.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { EnumInputShape, EnumOutputShape } from '@mysten/bcs';\nimport type { GenericSchema, InferInput, InferOutput, ObjectEntries, ObjectSchema } from 'valibot';\nimport {\n\tarray,\n\tboolean,\n\tcheck,\n\tinteger,\n\tlazy,\n\tliteral,\n\tnullable,\n\tnullish,\n\tnumber,\n\tobject,\n\toptional,\n\tpipe,\n\trecord,\n\tstring,\n\ttransform,\n\ttuple,\n\tunion,\n\tunknown,\n} from 'valibot';\n\nimport { isValidSuiAddress, normalizeSuiAddress } from '../../utils/sui-types.js';\nimport type { Simplify } from '@mysten/utils';\nimport type { SuiClientTypes } from '../../client/types.js';\n\ntype EnumSchemaInput<T extends Record<string, GenericSchema<any>>> = EnumInputShape<\n\tSimplify<{\n\t\t[K in keyof T]: InferInput<T[K]>;\n\t}>\n>;\n\ntype EnumSchemaOutput<T extends Record<string, GenericSchema<any>>> = EnumOutputShape<\n\tSimplify<{\n\t\t[K in keyof T]: InferOutput<T[K]>;\n\t}>\n>;\n\ntype EnumSchema<T extends Record<string, GenericSchema<any>>> = GenericSchema<\n\tEnumSchemaInput<T>,\n\tEnumSchemaOutput<T>\n>;\n\nexport function safeEnum<T extends Record<string, GenericSchema<any>>>(options: T): EnumSchema<T> {\n\treturn union(\n\t\tObject.keys(options).map(\n\t\t\t(key) =>\n\t\t\t\twithKind(\n\t\t\t\t\tkey,\n\t\t\t\t\tobject({\n\t\t\t\t\t\t[key]: options[key],\n\t\t\t\t\t}),\n\t\t\t\t) as GenericSchema<EnumOutputShape<T>>,\n\t\t),\n\t) as EnumSchema<T>;\n}\n\nfunction withKind<K extends string, TEntries extends ObjectEntries>(\n\tkey: K,\n\tschema: ObjectSchema<TEntries, undefined>,\n) {\n\treturn pipe(\n\t\tobject({\n\t\t\t...schema.entries,\n\t\t\t$kind: optional(literal(key)),\n\t\t}),\n\t\ttransform((value) => ({ ...value, $kind: key })),\n\t) as GenericSchema<\n\t\tSimplify<InferInput<ObjectSchema<TEntries, undefined>> & { $kind?: K }>,\n\t\tSimplify<InferOutput<ObjectSchema<TEntries, undefined>> & { $kind: K }>\n\t>;\n}\n\nexport const SuiAddress = pipe(\n\tstring(),\n\ttransform((value) => normalizeSuiAddress(value)),\n\tcheck(isValidSuiAddress),\n);\nexport const ObjectID = SuiAddress;\nexport const BCSBytes = string();\nexport const JsonU64 = pipe(\n\tunion([string(), pipe(number(), integer())]),\n\n\tcheck((val) => {\n\t\ttry {\n\t\t\tBigInt(val);\n\t\t\treturn BigInt(val) >= 0 && BigInt(val) <= 18446744073709551615n;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}, 'Invalid u64'),\n);\n\nexport const U32 = pipe(\n\tnumber(),\n\tinteger(),\n\tcheck((val) => val >= 0 && val < 2 ** 32, 'Invalid u32'),\n);\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/base_types.rs#L138\n// Implemented as a tuple in rust\nexport const ObjectRefSchema = object({\n\tobjectId: SuiAddress,\n\tversion: JsonU64,\n\tdigest: string(),\n});\nexport type ObjectRef = InferOutput<typeof ObjectRefSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L690-L702\nexport const ArgumentSchema = union([\n\twithKind('GasCoin', object({ GasCoin: literal(true) })),\n\twithKind(\n\t\t'Input',\n\t\tobject({\n\t\t\tInput: pipe(number(), integer()),\n\t\t\ttype: optional(union([literal('pure'), literal('object'), literal('withdrawal')])),\n\t\t}),\n\t),\n\twithKind('Result', object({ Result: pipe(number(), integer()) })),\n\twithKind(\n\t\t'NestedResult',\n\t\tobject({ NestedResult: tuple([pipe(number(), integer()), pipe(number(), integer())]) }),\n\t),\n]);\n\nexport type Argument = InferOutput<typeof ArgumentSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L1387-L1392\nexport const GasDataSchema = object({\n\tbudget: nullable(JsonU64),\n\tprice: nullable(JsonU64),\n\towner: nullable(SuiAddress),\n\tpayment: nullable(array(ObjectRefSchema)),\n});\nexport type GasData = InferOutput<typeof GasDataSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/external-crates/move/crates/move-core-types/src/language_storage.rs#L140-L147\nexport const StructTagSchema = object({\n\taddress: string(),\n\tmodule: string(),\n\tname: string(),\n\t// type_params in rust, should be updated to use camelCase\n\ttypeParams: array(string()),\n});\nexport type StructTag = InferOutput<typeof StructTagSchema>;\n\nexport const OpenSignatureBodySchema: GenericSchema<SuiClientTypes.OpenSignatureBody> = union([\n\tobject({ $kind: literal('address') }),\n\tobject({ $kind: literal('bool') }),\n\tobject({ $kind: literal('u8') }),\n\tobject({ $kind: literal('u16') }),\n\tobject({ $kind: literal('u32') }),\n\tobject({ $kind: literal('u64') }),\n\tobject({ $kind: literal('u128') }),\n\tobject({ $kind: literal('u256') }),\n\tobject({ $kind: literal('unknown') }),\n\tobject({ $kind: literal('vector'), vector: lazy(() => OpenSignatureBodySchema) }),\n\tobject({\n\t\t$kind: literal('datatype'),\n\t\tdatatype: object({\n\t\t\ttypeName: string(),\n\t\t\ttypeParameters: array(lazy(() => OpenSignatureBodySchema)),\n\t\t}),\n\t}),\n\tobject({ $kind: literal('typeParameter'), index: pipe(number(), integer()) }),\n]);\n\nexport const OpenSignatureSchema = object({\n\treference: nullable(union([literal('mutable'), literal('immutable'), literal('unknown')])),\n\tbody: OpenSignatureBodySchema,\n});\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L707-L718\nconst ProgrammableMoveCallSchema = object({\n\tpackage: ObjectID,\n\tmodule: string(),\n\tfunction: string(),\n\t// snake case in rust\n\ttypeArguments: array(string()),\n\targuments: array(ArgumentSchema),\n\t_argumentTypes: optional(nullable(array(OpenSignatureSchema))),\n});\nexport type ProgrammableMoveCall = InferOutput<typeof ProgrammableMoveCallSchema>;\n\nexport const $Intent = object({\n\tname: string(),\n\tinputs: record(string(), union([ArgumentSchema, array(ArgumentSchema)])),\n\tdata: record(string(), unknown()),\n});\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L657-L685\nexport const CommandSchema = safeEnum({\n\tMoveCall: ProgrammableMoveCallSchema,\n\tTransferObjects: object({\n\t\tobjects: array(ArgumentSchema),\n\t\taddress: ArgumentSchema,\n\t}),\n\tSplitCoins: object({\n\t\tcoin: ArgumentSchema,\n\t\tamounts: array(ArgumentSchema),\n\t}),\n\tMergeCoins: object({\n\t\tdestination: ArgumentSchema,\n\t\tsources: array(ArgumentSchema),\n\t}),\n\tPublish: object({\n\t\tmodules: array(BCSBytes),\n\t\tdependencies: array(ObjectID),\n\t}),\n\tMakeMoveVec: object({\n\t\ttype: nullable(string()),\n\t\telements: array(ArgumentSchema),\n\t}),\n\tUpgrade: object({\n\t\tmodules: array(BCSBytes),\n\t\tdependencies: array(ObjectID),\n\t\tpackage: ObjectID,\n\t\tticket: ArgumentSchema,\n\t}),\n\t$Intent,\n});\n\nexport type Command<Arg = Argument> = EnumOutputShape<{\n\tMoveCall: {\n\t\tpackage: string;\n\t\tmodule: string;\n\t\tfunction: string;\n\t\ttypeArguments: string[];\n\t\targuments: Arg[];\n\t\t_argumentTypes?: SuiClientTypes.OpenSignature[] | null;\n\t};\n\tTransferObjects: {\n\t\tobjects: Arg[];\n\t\taddress: Arg;\n\t};\n\tSplitCoins: {\n\t\tcoin: Arg;\n\t\tamounts: Arg[];\n\t};\n\tMergeCoins: {\n\t\tdestination: Arg;\n\t\tsources: Arg[];\n\t};\n\tPublish: {\n\t\tmodules: string[];\n\t\tdependencies: string[];\n\t};\n\tMakeMoveVec: {\n\t\ttype: string | null;\n\t\telements: Arg[];\n\t};\n\tUpgrade: {\n\t\tmodules: string[];\n\t\tdependencies: string[];\n\t\tpackage: string;\n\t\tticket: Arg;\n\t};\n\t$Intent: {\n\t\tname: string;\n\t\tinputs: Record<string, Argument | Argument[]>;\n\t\tdata: Record<string, unknown>;\n\t};\n}>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L102-L114\nexport const ObjectArgSchema = safeEnum({\n\tImmOrOwnedObject: ObjectRefSchema,\n\tSharedObject: object({\n\t\tobjectId: ObjectID,\n\t\t// snake case in rust\n\t\tinitialSharedVersion: JsonU64,\n\t\tmutable: boolean(),\n\t}),\n\tReceiving: ObjectRefSchema,\n});\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const ReservationSchema = safeEnum({\n\tMaxAmountU64: JsonU64,\n});\nexport type Reservation = InferOutput<typeof ReservationSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const WithdrawalTypeArgSchema = safeEnum({\n\tBalance: string(),\n});\nexport type WithdrawalTypeArg = InferOutput<typeof WithdrawalTypeArgSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const WithdrawFromSchema = safeEnum({\n\tSender: literal(true),\n\tSponsor: literal(true),\n});\nexport type WithdrawFrom = InferOutput<typeof WithdrawFromSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const FundsWithdrawalArgSchema = object({\n\treservation: ReservationSchema,\n\ttypeArg: WithdrawalTypeArgSchema,\n\twithdrawFrom: WithdrawFromSchema,\n});\nexport type FundsWithdrawalArg = InferOutput<typeof FundsWithdrawalArgSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L75-L80\nconst CallArgSchema = safeEnum({\n\tObject: ObjectArgSchema,\n\tPure: object({\n\t\tbytes: BCSBytes,\n\t}),\n\tUnresolvedPure: object({\n\t\tvalue: unknown(),\n\t}),\n\tUnresolvedObject: object({\n\t\tobjectId: ObjectID,\n\t\tversion: optional(nullable(JsonU64)),\n\t\tdigest: optional(nullable(string())),\n\t\tinitialSharedVersion: optional(nullable(JsonU64)),\n\t\tmutable: optional(nullable(boolean())),\n\t}),\n\tFundsWithdrawal: FundsWithdrawalArgSchema,\n});\nexport type CallArg = InferOutput<typeof CallArgSchema>;\n\nexport const NormalizedCallArg = safeEnum({\n\tObject: ObjectArgSchema,\n\tPure: object({\n\t\tbytes: BCSBytes,\n\t}),\n});\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const ValidDuringSchema = object({\n\tminEpoch: nullable(JsonU64),\n\tmaxEpoch: nullable(JsonU64),\n\tminTimestamp: nullable(JsonU64),\n\tmaxTimestamp: nullable(JsonU64),\n\tchain: string(),\n\tnonce: U32,\n});\nexport type ValidDuring = InferOutput<typeof ValidDuringSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const AllowedProposersSchema = object({\n\tepoch: JsonU64,\n\t// Shared by `setExpiration` and `restore`, so this can only carry the invariant true on both.\n\tproposers: pipe(\n\t\tarray(U32),\n\t\tcheck((proposers) => proposers.length > 0, 'Allowed proposers must not be empty'),\n\t),\n});\nexport type AllowedProposers = InferOutput<typeof AllowedProposersSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const ValiditySchema = object({\n\t...ValidDuringSchema.entries,\n\tallowedProposers: nullable(AllowedProposersSchema),\n});\nexport type Validity = InferOutput<typeof ValiditySchema>;\n\nexport const TransactionExpiration = safeEnum({\n\tNone: literal(true),\n\tEpoch: JsonU64,\n\tValidDuring: ValidDuringSchema,\n\tValidity: ValiditySchema,\n});\n\nexport type TransactionExpiration = InferOutput<typeof TransactionExpiration>;\n\nexport const TransactionDataSchema = object({\n\tversion: literal(2),\n\tsender: nullish(SuiAddress),\n\texpiration: nullish(TransactionExpiration),\n\tgasData: GasDataSchema,\n\tinputs: array(CallArgSchema),\n\tcommands: array(CommandSchema),\n});\n\nexport type TransactionData = InferOutput<typeof TransactionDataSchema>;\n"],"mappings":";;;;AA+CA,SAAgB,SAAuD,SAA2B;AACjG,QAAO,MACN,OAAO,KAAK,QAAQ,CAAC,KACnB,QACA,SACC,KACA,OAAO,GACL,MAAM,QAAQ,MACf,CAAC,CACF,CACF,CACD;;AAGF,SAAS,SACR,KACA,QACC;AACD,QAAO,KACN,OAAO;EACN,GAAG,OAAO;EACV,OAAO,SAAS,QAAQ,IAAI,CAAC;EAC7B,CAAC,EACF,WAAW,WAAW;EAAE,GAAG;EAAO,OAAO;EAAK,EAAE,CAChD;;AAMF,MAAa,aAAa,KACzB,QAAQ,EACR,WAAW,UAAU,oBAAoB,MAAM,CAAC,EAChD,MAAM,kBAAkB,CACxB;AACD,MAAa,WAAW;AACxB,MAAa,WAAW,QAAQ;AAChC,MAAa,UAAU,KACtB,MAAM,CAAC,QAAQ,EAAE,KAAK,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,EAE5C,OAAO,QAAQ;AACd,KAAI;AACH,SAAO,IAAI;AACX,SAAO,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI;SACnC;AACP,SAAO;;GAEN,cAAc,CACjB;AAED,MAAa,MAAM,KAClB,QAAQ,EACR,SAAS,EACT,OAAO,QAAQ,OAAO,KAAK,MAAM,KAAK,IAAI,cAAc,CACxD;AAID,MAAa,kBAAkB,OAAO;CACrC,UAAU;CACV,SAAS;CACT,QAAQ,QAAQ;CAChB,CAAC;AAIF,MAAa,iBAAiB,MAAM;CACnC,SAAS,WAAW,OAAO,EAAE,SAAS,QAAQ,KAAK,EAAE,CAAC,CAAC;CACvD,SACC,SACA,OAAO;EACN,OAAO,KAAK,QAAQ,EAAE,SAAS,CAAC;EAChC,MAAM,SAAS,MAAM;GAAC,QAAQ,OAAO;GAAE,QAAQ,SAAS;GAAE,QAAQ,aAAa;GAAC,CAAC,CAAC;EAClF,CAAC,CACF;CACD,SAAS,UAAU,OAAO,EAAE,QAAQ,KAAK,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;CACjE,SACC,gBACA,OAAO,EAAE,cAAc,MAAM,CAAC,KAAK,QAAQ,EAAE,SAAS,CAAC,EAAE,KAAK,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CACvF;CACD,CAAC;AAKF,MAAa,gBAAgB,OAAO;CACnC,QAAQ,SAAS,QAAQ;CACzB,OAAO,SAAS,QAAQ;CACxB,OAAO,SAAS,WAAW;CAC3B,SAAS,SAAS,MAAM,gBAAgB,CAAC;CACzC,CAAC;AAIF,MAAa,kBAAkB,OAAO;CACrC,SAAS,QAAQ;CACjB,QAAQ,QAAQ;CAChB,MAAM,QAAQ;CAEd,YAAY,MAAM,QAAQ,CAAC;CAC3B,CAAC;AAGF,MAAa,0BAA2E,MAAM;CAC7F,OAAO,EAAE,OAAO,QAAQ,UAAU,EAAE,CAAC;CACrC,OAAO,EAAE,OAAO,QAAQ,OAAO,EAAE,CAAC;CAClC,OAAO,EAAE,OAAO,QAAQ,KAAK,EAAE,CAAC;CAChC,OAAO,EAAE,OAAO,QAAQ,MAAM,EAAE,CAAC;CACjC,OAAO,EAAE,OAAO,QAAQ,MAAM,EAAE,CAAC;CACjC,OAAO,EAAE,OAAO,QAAQ,MAAM,EAAE,CAAC;CACjC,OAAO,EAAE,OAAO,QAAQ,OAAO,EAAE,CAAC;CAClC,OAAO,EAAE,OAAO,QAAQ,OAAO,EAAE,CAAC;CAClC,OAAO,EAAE,OAAO,QAAQ,UAAU,EAAE,CAAC;CACrC,OAAO;EAAE,OAAO,QAAQ,SAAS;EAAE,QAAQ,WAAW,wBAAwB;EAAE,CAAC;CACjF,OAAO;EACN,OAAO,QAAQ,WAAW;EAC1B,UAAU,OAAO;GAChB,UAAU,QAAQ;GAClB,gBAAgB,MAAM,WAAW,wBAAwB,CAAC;GAC1D,CAAC;EACF,CAAC;CACF,OAAO;EAAE,OAAO,QAAQ,gBAAgB;EAAE,OAAO,KAAK,QAAQ,EAAE,SAAS,CAAC;EAAE,CAAC;CAC7E,CAAC;AAEF,MAAa,sBAAsB,OAAO;CACzC,WAAW,SAAS,MAAM;EAAC,QAAQ,UAAU;EAAE,QAAQ,YAAY;EAAE,QAAQ,UAAU;EAAC,CAAC,CAAC;CAC1F,MAAM;CACN,CAAC;AAGF,MAAM,6BAA6B,OAAO;CACzC,SAAS;CACT,QAAQ,QAAQ;CAChB,UAAU,QAAQ;CAElB,eAAe,MAAM,QAAQ,CAAC;CAC9B,WAAW,MAAM,eAAe;CAChC,gBAAgB,SAAS,SAAS,MAAM,oBAAoB,CAAC,CAAC;CAC9D,CAAC;AAGF,MAAa,UAAU,OAAO;CAC7B,MAAM,QAAQ;CACd,QAAQ,OAAO,QAAQ,EAAE,MAAM,CAAC,gBAAgB,MAAM,eAAe,CAAC,CAAC,CAAC;CACxE,MAAM,OAAO,QAAQ,EAAE,SAAS,CAAC;CACjC,CAAC;AAGF,MAAa,gBAAgB,SAAS;CACrC,UAAU;CACV,iBAAiB,OAAO;EACvB,SAAS,MAAM,eAAe;EAC9B,SAAS;EACT,CAAC;CACF,YAAY,OAAO;EAClB,MAAM;EACN,SAAS,MAAM,eAAe;EAC9B,CAAC;CACF,YAAY,OAAO;EAClB,aAAa;EACb,SAAS,MAAM,eAAe;EAC9B,CAAC;CACF,SAAS,OAAO;EACf,SAAS,MAAM,SAAS;EACxB,cAAc,MAAM,SAAS;EAC7B,CAAC;CACF,aAAa,OAAO;EACnB,MAAM,SAAS,QAAQ,CAAC;EACxB,UAAU,MAAM,eAAe;EAC/B,CAAC;CACF,SAAS,OAAO;EACf,SAAS,MAAM,SAAS;EACxB,cAAc,MAAM,SAAS;EAC7B,SAAS;EACT,QAAQ;EACR,CAAC;CACF;CACA,CAAC;AA6CF,MAAa,kBAAkB,SAAS;CACvC,kBAAkB;CAClB,cAAc,OAAO;EACpB,UAAU;EAEV,sBAAsB;EACtB,SAAS,SAAS;EAClB,CAAC;CACF,WAAW;CACX,CAAC;AAGF,MAAa,oBAAoB,SAAS,EACzC,cAAc,SACd,CAAC;AAIF,MAAa,0BAA0B,SAAS,EAC/C,SAAS,QAAQ,EACjB,CAAC;AAIF,MAAa,qBAAqB,SAAS;CAC1C,QAAQ,QAAQ,KAAK;CACrB,SAAS,QAAQ,KAAK;CACtB,CAAC;AAIF,MAAa,2BAA2B,OAAO;CAC9C,aAAa;CACb,SAAS;CACT,cAAc;CACd,CAAC;AAIF,MAAM,gBAAgB,SAAS;CAC9B,QAAQ;CACR,MAAM,OAAO,EACZ,OAAO,UACP,CAAC;CACF,gBAAgB,OAAO,EACtB,OAAO,SAAS,EAChB,CAAC;CACF,kBAAkB,OAAO;EACxB,UAAU;EACV,SAAS,SAAS,SAAS,QAAQ,CAAC;EACpC,QAAQ,SAAS,SAAS,QAAQ,CAAC,CAAC;EACpC,sBAAsB,SAAS,SAAS,QAAQ,CAAC;EACjD,SAAS,SAAS,SAAS,SAAS,CAAC,CAAC;EACtC,CAAC;CACF,iBAAiB;CACjB,CAAC;AAGF,MAAa,oBAAoB,SAAS;CACzC,QAAQ;CACR,MAAM,OAAO,EACZ,OAAO,UACP,CAAC;CACF,CAAC;AAGF,MAAa,oBAAoB,OAAO;CACvC,UAAU,SAAS,QAAQ;CAC3B,UAAU,SAAS,QAAQ;CAC3B,cAAc,SAAS,QAAQ;CAC/B,cAAc,SAAS,QAAQ;CAC/B,OAAO,QAAQ;CACf,OAAO;CACP,CAAC;AAIF,MAAa,yBAAyB,OAAO;CAC5C,OAAO;CAEP,WAAW,KACV,MAAM,IAAI,EACV,OAAO,cAAc,UAAU,SAAS,GAAG,sCAAsC,CACjF;CACD,CAAC;AAIF,MAAa,iBAAiB,OAAO;CACpC,GAAG,kBAAkB;CACrB,kBAAkB,SAAS,uBAAuB;CAClD,CAAC;AAGF,MAAa,wBAAwB,SAAS;CAC7C,MAAM,QAAQ,KAAK;CACnB,OAAO;CACP,aAAa;CACb,UAAU;CACV,CAAC;AAIF,MAAa,wBAAwB,OAAO;CAC3C,SAAS,QAAQ,EAAE;CACnB,QAAQ,QAAQ,WAAW;CAC3B,YAAY,QAAQ,sBAAsB;CAC1C,SAAS;CACT,QAAQ,MAAM,cAAc;CAC5B,UAAU,MAAM,cAAc;CAC9B,CAAC"}
|
|
1
|
+
{"version":3,"file":"internal.mjs","names":[],"sources":["../../../src/transactions/data/internal.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { EnumInputShape, EnumOutputShape } from '@mysten/bcs';\nimport type { GenericSchema, InferInput, InferOutput, ObjectEntries, ObjectSchema } from 'valibot';\nimport {\n\tarray,\n\tboolean,\n\tcheck,\n\tinteger,\n\tlazy,\n\tliteral,\n\tnullable,\n\tnullish,\n\tnumber,\n\tobject,\n\toptional,\n\tpipe,\n\trecord,\n\tstring,\n\ttransform,\n\ttuple,\n\tunion,\n\tunknown,\n} from 'valibot';\n\nimport { isValidSuiAddress, normalizeSuiAddress } from '../../utils/sui-types.js';\nimport type { Simplify } from '@mysten/utils';\nimport type { SuiClientTypes } from '../../client/types.js';\n\ntype EnumSchemaInput<T extends Record<string, GenericSchema<any>>> = EnumInputShape<\n\tSimplify<{\n\t\t[K in keyof T]: InferInput<T[K]>;\n\t}>\n>;\n\ntype EnumSchemaOutput<T extends Record<string, GenericSchema<any>>> = EnumOutputShape<\n\tSimplify<{\n\t\t[K in keyof T]: InferOutput<T[K]>;\n\t}>\n>;\n\ntype EnumSchema<T extends Record<string, GenericSchema<any>>> = GenericSchema<\n\tEnumSchemaInput<T>,\n\tEnumSchemaOutput<T>\n>;\n\nexport function safeEnum<T extends Record<string, GenericSchema<any>>>(options: T): EnumSchema<T> {\n\treturn union(\n\t\tObject.keys(options).map(\n\t\t\t(key) =>\n\t\t\t\twithKind(\n\t\t\t\t\tkey,\n\t\t\t\t\tobject({\n\t\t\t\t\t\t[key]: options[key],\n\t\t\t\t\t}),\n\t\t\t\t) as GenericSchema<EnumOutputShape<T>>,\n\t\t),\n\t) as EnumSchema<T>;\n}\n\nfunction withKind<K extends string, TEntries extends ObjectEntries>(\n\tkey: K,\n\tschema: ObjectSchema<TEntries, undefined>,\n) {\n\treturn pipe(\n\t\tobject({\n\t\t\t...schema.entries,\n\t\t\t$kind: optional(literal(key)),\n\t\t}),\n\t\ttransform((value) => ({ ...value, $kind: key })),\n\t) as GenericSchema<\n\t\tSimplify<InferInput<ObjectSchema<TEntries, undefined>> & { $kind?: K }>,\n\t\tSimplify<InferOutput<ObjectSchema<TEntries, undefined>> & { $kind: K }>\n\t>;\n}\n\nexport const SuiAddress = pipe(\n\tstring(),\n\ttransform((value) => normalizeSuiAddress(value)),\n\tcheck(isValidSuiAddress),\n);\nexport const ObjectID = SuiAddress;\nexport const BCSBytes = string();\nexport const JsonU64 = pipe(\n\tunion([string(), pipe(number(), integer())]),\n\n\tcheck((val) => {\n\t\ttry {\n\t\t\tBigInt(val);\n\t\t\treturn BigInt(val) >= 0 && BigInt(val) <= 18446744073709551615n;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}, 'Invalid u64'),\n);\n\nexport const U32 = pipe(\n\tnumber(),\n\tinteger(),\n\tcheck((val) => val >= 0 && val < 2 ** 32, 'Invalid u32'),\n);\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/base_types.rs#L138\n// Implemented as a tuple in rust\nexport const ObjectRefSchema = object({\n\tobjectId: SuiAddress,\n\tversion: JsonU64,\n\tdigest: string(),\n});\nexport type ObjectRef = InferOutput<typeof ObjectRefSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L690-L702\nexport const ArgumentSchema = union([\n\twithKind('GasCoin', object({ GasCoin: literal(true) })),\n\twithKind(\n\t\t'Input',\n\t\tobject({\n\t\t\tInput: pipe(number(), integer()),\n\t\t\ttype: optional(union([literal('pure'), literal('object'), literal('withdrawal')])),\n\t\t}),\n\t),\n\twithKind('Result', object({ Result: pipe(number(), integer()) })),\n\twithKind(\n\t\t'NestedResult',\n\t\tobject({ NestedResult: tuple([pipe(number(), integer()), pipe(number(), integer())]) }),\n\t),\n]);\n\nexport type Argument = InferOutput<typeof ArgumentSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L1387-L1392\nexport const GasDataSchema = object({\n\tbudget: nullable(JsonU64),\n\tprice: nullable(JsonU64),\n\towner: nullable(SuiAddress),\n\tpayment: nullable(array(ObjectRefSchema)),\n});\nexport type GasData = InferOutput<typeof GasDataSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/external-crates/move/crates/move-core-types/src/language_storage.rs#L140-L147\nexport const StructTagSchema = object({\n\taddress: string(),\n\tmodule: string(),\n\tname: string(),\n\t// type_params in rust, should be updated to use camelCase\n\ttypeParams: array(string()),\n});\nexport type StructTag = InferOutput<typeof StructTagSchema>;\n\nexport const OpenSignatureBodySchema: GenericSchema<SuiClientTypes.OpenSignatureBody> = union([\n\tobject({ $kind: literal('address') }),\n\tobject({ $kind: literal('bool') }),\n\tobject({ $kind: literal('u8') }),\n\tobject({ $kind: literal('u16') }),\n\tobject({ $kind: literal('u32') }),\n\tobject({ $kind: literal('u64') }),\n\tobject({ $kind: literal('u128') }),\n\tobject({ $kind: literal('u256') }),\n\tobject({ $kind: literal('unknown') }),\n\tobject({ $kind: literal('vector'), vector: lazy(() => OpenSignatureBodySchema) }),\n\tobject({\n\t\t$kind: literal('datatype'),\n\t\tdatatype: object({\n\t\t\ttypeName: string(),\n\t\t\ttypeParameters: array(lazy(() => OpenSignatureBodySchema)),\n\t\t}),\n\t}),\n\tobject({ $kind: literal('typeParameter'), index: pipe(number(), integer()) }),\n]);\n\nexport const OpenSignatureSchema = object({\n\treference: nullable(union([literal('mutable'), literal('immutable'), literal('unknown')])),\n\tbody: OpenSignatureBodySchema,\n});\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L707-L718\nconst ProgrammableMoveCallSchema = object({\n\tpackage: ObjectID,\n\tmodule: string(),\n\tfunction: string(),\n\t// snake case in rust\n\ttypeArguments: array(string()),\n\targuments: array(ArgumentSchema),\n\t_argumentTypes: optional(nullable(array(OpenSignatureSchema))),\n});\nexport type ProgrammableMoveCall = InferOutput<typeof ProgrammableMoveCallSchema>;\n\nexport const $Intent = object({\n\tname: string(),\n\tinputs: record(string(), union([ArgumentSchema, array(ArgumentSchema)])),\n\tdata: record(string(), unknown()),\n});\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L657-L685\nexport const CommandSchema = safeEnum({\n\tMoveCall: ProgrammableMoveCallSchema,\n\tTransferObjects: object({\n\t\tobjects: array(ArgumentSchema),\n\t\taddress: ArgumentSchema,\n\t}),\n\tSplitCoins: object({\n\t\tcoin: ArgumentSchema,\n\t\tamounts: array(ArgumentSchema),\n\t}),\n\tMergeCoins: object({\n\t\tdestination: ArgumentSchema,\n\t\tsources: array(ArgumentSchema),\n\t}),\n\tPublish: object({\n\t\tmodules: array(BCSBytes),\n\t\tdependencies: array(ObjectID),\n\t}),\n\tMakeMoveVec: object({\n\t\ttype: nullable(string()),\n\t\telements: array(ArgumentSchema),\n\t}),\n\tUpgrade: object({\n\t\tmodules: array(BCSBytes),\n\t\tdependencies: array(ObjectID),\n\t\tpackage: ObjectID,\n\t\tticket: ArgumentSchema,\n\t}),\n\t$Intent,\n});\n\nexport type Command<Arg = Argument> = EnumOutputShape<{\n\tMoveCall: {\n\t\tpackage: string;\n\t\tmodule: string;\n\t\tfunction: string;\n\t\ttypeArguments: string[];\n\t\targuments: Arg[];\n\t\t_argumentTypes?: SuiClientTypes.OpenSignature[] | null;\n\t};\n\tTransferObjects: {\n\t\tobjects: Arg[];\n\t\taddress: Arg;\n\t};\n\tSplitCoins: {\n\t\tcoin: Arg;\n\t\tamounts: Arg[];\n\t};\n\tMergeCoins: {\n\t\tdestination: Arg;\n\t\tsources: Arg[];\n\t};\n\tPublish: {\n\t\tmodules: string[];\n\t\tdependencies: string[];\n\t};\n\tMakeMoveVec: {\n\t\ttype: string | null;\n\t\telements: Arg[];\n\t};\n\tUpgrade: {\n\t\tmodules: string[];\n\t\tdependencies: string[];\n\t\tpackage: string;\n\t\tticket: Arg;\n\t};\n\t$Intent: {\n\t\tname: string;\n\t\tinputs: Record<string, Argument | Argument[]>;\n\t\tdata: Record<string, unknown>;\n\t};\n}>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L102-L114\nexport const ObjectArgSchema = safeEnum({\n\tImmOrOwnedObject: ObjectRefSchema,\n\tSharedObject: object({\n\t\tobjectId: ObjectID,\n\t\t// snake case in rust\n\t\tinitialSharedVersion: JsonU64,\n\t\tmutable: boolean(),\n\t}),\n\tReceiving: ObjectRefSchema,\n});\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const ReservationSchema = safeEnum({\n\tMaxAmountU64: JsonU64,\n});\nexport type Reservation = InferOutput<typeof ReservationSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const WithdrawalTypeArgSchema = safeEnum({\n\tBalance: string(),\n});\nexport type WithdrawalTypeArg = InferOutput<typeof WithdrawalTypeArgSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const WithdrawFromSchema = safeEnum({\n\tSender: literal(true),\n\tSponsor: literal(true),\n\tSenderAllowance: object({\n\t\tfunder: SuiAddress,\n\t\tallowance: ObjectID,\n\t}),\n});\nexport type WithdrawFrom = InferOutput<typeof WithdrawFromSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const FundsWithdrawalArgSchema = object({\n\treservation: ReservationSchema,\n\ttypeArg: WithdrawalTypeArgSchema,\n\twithdrawFrom: WithdrawFromSchema,\n});\nexport type FundsWithdrawalArg = InferOutput<typeof FundsWithdrawalArgSchema>;\n\n// https://github.com/MystenLabs/sui/blob/df41d5fa8127634ff4285671a01ead00e519f806/crates/sui-types/src/transaction.rs#L75-L80\nconst CallArgSchema = safeEnum({\n\tObject: ObjectArgSchema,\n\tPure: object({\n\t\tbytes: BCSBytes,\n\t}),\n\tUnresolvedPure: object({\n\t\tvalue: unknown(),\n\t}),\n\tUnresolvedObject: object({\n\t\tobjectId: ObjectID,\n\t\tversion: optional(nullable(JsonU64)),\n\t\tdigest: optional(nullable(string())),\n\t\tinitialSharedVersion: optional(nullable(JsonU64)),\n\t\tmutable: optional(nullable(boolean())),\n\t}),\n\tFundsWithdrawal: FundsWithdrawalArgSchema,\n});\nexport type CallArg = InferOutput<typeof CallArgSchema>;\n\nexport const NormalizedCallArg = safeEnum({\n\tObject: ObjectArgSchema,\n\tPure: object({\n\t\tbytes: BCSBytes,\n\t}),\n});\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const ValidDuringSchema = object({\n\tminEpoch: nullable(JsonU64),\n\tmaxEpoch: nullable(JsonU64),\n\tminTimestamp: nullable(JsonU64),\n\tmaxTimestamp: nullable(JsonU64),\n\tchain: string(),\n\tnonce: U32,\n});\nexport type ValidDuring = InferOutput<typeof ValidDuringSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const AllowedProposersSchema = object({\n\tepoch: JsonU64,\n\t// Shared by `setExpiration` and `restore`, so this can only carry the invariant true on both.\n\tproposers: pipe(\n\t\tarray(U32),\n\t\tcheck((proposers) => proposers.length > 0, 'Allowed proposers must not be empty'),\n\t),\n});\nexport type AllowedProposers = InferOutput<typeof AllowedProposersSchema>;\n\n// Rust: crates/sui-types/src/transaction.rs\nexport const ValiditySchema = object({\n\t...ValidDuringSchema.entries,\n\tallowedProposers: nullable(AllowedProposersSchema),\n});\nexport type Validity = InferOutput<typeof ValiditySchema>;\n\nexport const TransactionExpiration = safeEnum({\n\tNone: literal(true),\n\tEpoch: JsonU64,\n\tValidDuring: ValidDuringSchema,\n\tValidity: ValiditySchema,\n});\n\nexport type TransactionExpiration = InferOutput<typeof TransactionExpiration>;\n\nexport const TransactionDataSchema = object({\n\tversion: literal(2),\n\tsender: nullish(SuiAddress),\n\texpiration: nullish(TransactionExpiration),\n\tgasData: GasDataSchema,\n\tinputs: array(CallArgSchema),\n\tcommands: array(CommandSchema),\n});\n\nexport type TransactionData = InferOutput<typeof TransactionDataSchema>;\n"],"mappings":";;;;AA+CA,SAAgB,SAAuD,SAA2B;AACjG,QAAO,MACN,OAAO,KAAK,QAAQ,CAAC,KACnB,QACA,SACC,KACA,OAAO,GACL,MAAM,QAAQ,MACf,CAAC,CACF,CACF,CACD;;AAGF,SAAS,SACR,KACA,QACC;AACD,QAAO,KACN,OAAO;EACN,GAAG,OAAO;EACV,OAAO,SAAS,QAAQ,IAAI,CAAC;EAC7B,CAAC,EACF,WAAW,WAAW;EAAE,GAAG;EAAO,OAAO;EAAK,EAAE,CAChD;;AAMF,MAAa,aAAa,KACzB,QAAQ,EACR,WAAW,UAAU,oBAAoB,MAAM,CAAC,EAChD,MAAM,kBAAkB,CACxB;AACD,MAAa,WAAW;AACxB,MAAa,WAAW,QAAQ;AAChC,MAAa,UAAU,KACtB,MAAM,CAAC,QAAQ,EAAE,KAAK,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,EAE5C,OAAO,QAAQ;AACd,KAAI;AACH,SAAO,IAAI;AACX,SAAO,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI;SACnC;AACP,SAAO;;GAEN,cAAc,CACjB;AAED,MAAa,MAAM,KAClB,QAAQ,EACR,SAAS,EACT,OAAO,QAAQ,OAAO,KAAK,MAAM,KAAK,IAAI,cAAc,CACxD;AAID,MAAa,kBAAkB,OAAO;CACrC,UAAU;CACV,SAAS;CACT,QAAQ,QAAQ;CAChB,CAAC;AAIF,MAAa,iBAAiB,MAAM;CACnC,SAAS,WAAW,OAAO,EAAE,SAAS,QAAQ,KAAK,EAAE,CAAC,CAAC;CACvD,SACC,SACA,OAAO;EACN,OAAO,KAAK,QAAQ,EAAE,SAAS,CAAC;EAChC,MAAM,SAAS,MAAM;GAAC,QAAQ,OAAO;GAAE,QAAQ,SAAS;GAAE,QAAQ,aAAa;GAAC,CAAC,CAAC;EAClF,CAAC,CACF;CACD,SAAS,UAAU,OAAO,EAAE,QAAQ,KAAK,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;CACjE,SACC,gBACA,OAAO,EAAE,cAAc,MAAM,CAAC,KAAK,QAAQ,EAAE,SAAS,CAAC,EAAE,KAAK,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CACvF;CACD,CAAC;AAKF,MAAa,gBAAgB,OAAO;CACnC,QAAQ,SAAS,QAAQ;CACzB,OAAO,SAAS,QAAQ;CACxB,OAAO,SAAS,WAAW;CAC3B,SAAS,SAAS,MAAM,gBAAgB,CAAC;CACzC,CAAC;AAIF,MAAa,kBAAkB,OAAO;CACrC,SAAS,QAAQ;CACjB,QAAQ,QAAQ;CAChB,MAAM,QAAQ;CAEd,YAAY,MAAM,QAAQ,CAAC;CAC3B,CAAC;AAGF,MAAa,0BAA2E,MAAM;CAC7F,OAAO,EAAE,OAAO,QAAQ,UAAU,EAAE,CAAC;CACrC,OAAO,EAAE,OAAO,QAAQ,OAAO,EAAE,CAAC;CAClC,OAAO,EAAE,OAAO,QAAQ,KAAK,EAAE,CAAC;CAChC,OAAO,EAAE,OAAO,QAAQ,MAAM,EAAE,CAAC;CACjC,OAAO,EAAE,OAAO,QAAQ,MAAM,EAAE,CAAC;CACjC,OAAO,EAAE,OAAO,QAAQ,MAAM,EAAE,CAAC;CACjC,OAAO,EAAE,OAAO,QAAQ,OAAO,EAAE,CAAC;CAClC,OAAO,EAAE,OAAO,QAAQ,OAAO,EAAE,CAAC;CAClC,OAAO,EAAE,OAAO,QAAQ,UAAU,EAAE,CAAC;CACrC,OAAO;EAAE,OAAO,QAAQ,SAAS;EAAE,QAAQ,WAAW,wBAAwB;EAAE,CAAC;CACjF,OAAO;EACN,OAAO,QAAQ,WAAW;EAC1B,UAAU,OAAO;GAChB,UAAU,QAAQ;GAClB,gBAAgB,MAAM,WAAW,wBAAwB,CAAC;GAC1D,CAAC;EACF,CAAC;CACF,OAAO;EAAE,OAAO,QAAQ,gBAAgB;EAAE,OAAO,KAAK,QAAQ,EAAE,SAAS,CAAC;EAAE,CAAC;CAC7E,CAAC;AAEF,MAAa,sBAAsB,OAAO;CACzC,WAAW,SAAS,MAAM;EAAC,QAAQ,UAAU;EAAE,QAAQ,YAAY;EAAE,QAAQ,UAAU;EAAC,CAAC,CAAC;CAC1F,MAAM;CACN,CAAC;AAGF,MAAM,6BAA6B,OAAO;CACzC,SAAS;CACT,QAAQ,QAAQ;CAChB,UAAU,QAAQ;CAElB,eAAe,MAAM,QAAQ,CAAC;CAC9B,WAAW,MAAM,eAAe;CAChC,gBAAgB,SAAS,SAAS,MAAM,oBAAoB,CAAC,CAAC;CAC9D,CAAC;AAGF,MAAa,UAAU,OAAO;CAC7B,MAAM,QAAQ;CACd,QAAQ,OAAO,QAAQ,EAAE,MAAM,CAAC,gBAAgB,MAAM,eAAe,CAAC,CAAC,CAAC;CACxE,MAAM,OAAO,QAAQ,EAAE,SAAS,CAAC;CACjC,CAAC;AAGF,MAAa,gBAAgB,SAAS;CACrC,UAAU;CACV,iBAAiB,OAAO;EACvB,SAAS,MAAM,eAAe;EAC9B,SAAS;EACT,CAAC;CACF,YAAY,OAAO;EAClB,MAAM;EACN,SAAS,MAAM,eAAe;EAC9B,CAAC;CACF,YAAY,OAAO;EAClB,aAAa;EACb,SAAS,MAAM,eAAe;EAC9B,CAAC;CACF,SAAS,OAAO;EACf,SAAS,MAAM,SAAS;EACxB,cAAc,MAAM,SAAS;EAC7B,CAAC;CACF,aAAa,OAAO;EACnB,MAAM,SAAS,QAAQ,CAAC;EACxB,UAAU,MAAM,eAAe;EAC/B,CAAC;CACF,SAAS,OAAO;EACf,SAAS,MAAM,SAAS;EACxB,cAAc,MAAM,SAAS;EAC7B,SAAS;EACT,QAAQ;EACR,CAAC;CACF;CACA,CAAC;AA6CF,MAAa,kBAAkB,SAAS;CACvC,kBAAkB;CAClB,cAAc,OAAO;EACpB,UAAU;EAEV,sBAAsB;EACtB,SAAS,SAAS;EAClB,CAAC;CACF,WAAW;CACX,CAAC;AAGF,MAAa,oBAAoB,SAAS,EACzC,cAAc,SACd,CAAC;AAIF,MAAa,0BAA0B,SAAS,EAC/C,SAAS,QAAQ,EACjB,CAAC;AAIF,MAAa,qBAAqB,SAAS;CAC1C,QAAQ,QAAQ,KAAK;CACrB,SAAS,QAAQ,KAAK;CACtB,iBAAiB,OAAO;EACvB,QAAQ;EACR,WAAW;EACX,CAAC;CACF,CAAC;AAIF,MAAa,2BAA2B,OAAO;CAC9C,aAAa;CACb,SAAS;CACT,cAAc;CACd,CAAC;AAIF,MAAM,gBAAgB,SAAS;CAC9B,QAAQ;CACR,MAAM,OAAO,EACZ,OAAO,UACP,CAAC;CACF,gBAAgB,OAAO,EACtB,OAAO,SAAS,EAChB,CAAC;CACF,kBAAkB,OAAO;EACxB,UAAU;EACV,SAAS,SAAS,SAAS,QAAQ,CAAC;EACpC,QAAQ,SAAS,SAAS,QAAQ,CAAC,CAAC;EACpC,sBAAsB,SAAS,SAAS,QAAQ,CAAC;EACjD,SAAS,SAAS,SAAS,SAAS,CAAC,CAAC;EACtC,CAAC;CACF,iBAAiB;CACjB,CAAC;AAGF,MAAa,oBAAoB,SAAS;CACzC,QAAQ;CACR,MAAM,OAAO,EACZ,OAAO,UACP,CAAC;CACF,CAAC;AAGF,MAAa,oBAAoB,OAAO;CACvC,UAAU,SAAS,QAAQ;CAC3B,UAAU,SAAS,QAAQ;CAC3B,cAAc,SAAS,QAAQ;CAC/B,cAAc,SAAS,QAAQ;CAC/B,OAAO,QAAQ;CACf,OAAO;CACP,CAAC;AAIF,MAAa,yBAAyB,OAAO;CAC5C,OAAO;CAEP,WAAW,KACV,MAAM,IAAI,EACV,OAAO,cAAc,UAAU,SAAS,GAAG,sCAAsC,CACjF;CACD,CAAC;AAIF,MAAa,iBAAiB,OAAO;CACpC,GAAG,kBAAkB;CACrB,kBAAkB,SAAS,uBAAuB;CAClD,CAAC;AAGF,MAAa,wBAAwB,SAAS;CAC7C,MAAM,QAAQ,KAAK;CACnB,OAAO;CACP,aAAa;CACb,UAAU;CACV,CAAC;AAIF,MAAa,wBAAwB,OAAO;CAC3C,SAAS,QAAQ,EAAE;CACnB,QAAQ,QAAQ,WAAW;CAC3B,YAAY,QAAQ,sBAAsB;CAC1C,SAAS;CACT,QAAQ,MAAM,cAAc;CAC5B,UAAU,MAAM,cAAc;CAC9B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.d.mts","names":[],"sources":["../../../src/transactions/data/v2.ts"],"mappings":";;;;;cAqJa,iCAAA,WAAiC,YAAA;EAAA,kBAQ5C,QAAA,CAAA,aAAA;EAAA
|
|
1
|
+
{"version":3,"file":"v2.d.mts","names":[],"sources":["../../../src/transactions/data/v2.ts"],"mappings":";;;;;cAqJa,iCAAA,WAAiC,YAAA;EAAA,kBAQ5C,QAAA,CAAA,aAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEU,2BAAA,GAA8B,WAAA,QAAmB,iCAAA"}
|
|
@@ -5,7 +5,8 @@ import { SerializedTransactionDataV1 } from "./data/v1.mjs";
|
|
|
5
5
|
import { SerializedTransactionDataV2 } from "./data/v2.mjs";
|
|
6
6
|
import { TransactionDataBuilder } from "./TransactionData.mjs";
|
|
7
7
|
import { BuildTransactionOptions, SerializeTransactionOptions, TransactionPlugin } from "./resolve.mjs";
|
|
8
|
-
import {
|
|
8
|
+
import { AllowanceReference, BalanceOptions } from "./intents/BalanceOptions.mjs";
|
|
9
|
+
import { Transaction, TransactionCopyOptions, TransactionObjectArgument, TransactionObjectInput, TransactionResult, WithdrawalOptions, isTransaction } from "./Transaction.mjs";
|
|
9
10
|
import { getPureBcsSchema, normalizedTypeToMoveTypeSignature } from "./serializer.mjs";
|
|
10
11
|
import { AsyncCache, ObjectCache } from "./ObjectCache.mjs";
|
|
11
12
|
import { SerialTransactionExecutor } from "./executor/serial.mjs";
|
|
@@ -13,4 +14,4 @@ import { ParallelTransactionExecutor, ParallelTransactionExecutorOptions } from
|
|
|
13
14
|
import { coinWithBalance } from "./intents/CoinWithBalance.mjs";
|
|
14
15
|
import { Arguments } from "./Arguments.mjs";
|
|
15
16
|
import { isArgument } from "./utils.mjs";
|
|
16
|
-
export { type Argument, Arguments, AsyncCache, type BuildTransactionOptions, type CallArg, type Command, type GasData, Inputs, ObjectCache, type ObjectRef, ParallelTransactionExecutor, type ParallelTransactionExecutorOptions, SerialTransactionExecutor, type SerializeTransactionOptions, type SerializedTransactionDataV1, type SerializedTransactionDataV2, Transaction, type TransactionArgument, TransactionCommands, type TransactionCopyOptions, type TransactionData, TransactionDataBuilder, type TransactionInput, type TransactionObjectArgument, type TransactionObjectInput, type TransactionPlugin, type TransactionResult, UpgradePolicy, coinWithBalance, getPureBcsSchema, isArgument, isTransaction, normalizedTypeToMoveTypeSignature };
|
|
17
|
+
export { type AllowanceReference, type Argument, Arguments, AsyncCache, type BalanceOptions, type BuildTransactionOptions, type CallArg, type Command, type GasData, Inputs, ObjectCache, type ObjectRef, ParallelTransactionExecutor, type ParallelTransactionExecutorOptions, SerialTransactionExecutor, type SerializeTransactionOptions, type SerializedTransactionDataV1, type SerializedTransactionDataV2, Transaction, type TransactionArgument, TransactionCommands, type TransactionCopyOptions, type TransactionData, TransactionDataBuilder, type TransactionInput, type TransactionObjectArgument, type TransactionObjectInput, type TransactionPlugin, type TransactionResult, UpgradePolicy, type WithdrawalOptions, coinWithBalance, getPureBcsSchema, isArgument, isTransaction, normalizedTypeToMoveTypeSignature };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { normalizeStructTag, normalizeSuiAddress } from "../../utils/sui-types.mjs";
|
|
2
|
+
import { bcs as suiBcs } from "../../bcs/index.mjs";
|
|
3
|
+
import { hasMvrName } from "../../client/mvr.mjs";
|
|
4
|
+
import { TransactionCommands } from "../Commands.mjs";
|
|
5
|
+
import { Inputs } from "../Inputs.mjs";
|
|
6
|
+
import { getClient } from "../resolve.mjs";
|
|
7
|
+
import { ALLOWANCE_BALANCE } from "./BalanceIntentNames.mjs";
|
|
8
|
+
import { resolveBalances } from "./ResolveBalances.mjs";
|
|
9
|
+
import { object, optional, parse, picklist, string } from "valibot";
|
|
10
|
+
|
|
11
|
+
//#region src/transactions/intents/AllowanceBalance.ts
|
|
12
|
+
const AllowanceBalanceData = object({
|
|
13
|
+
objectId: string(),
|
|
14
|
+
funder: optional(string()),
|
|
15
|
+
appType: optional(string()),
|
|
16
|
+
type: string(),
|
|
17
|
+
amount: string(),
|
|
18
|
+
outputKind: picklist(["coin", "balance"])
|
|
19
|
+
});
|
|
20
|
+
const AllowanceMetadata = suiBcs.struct("AllowanceMetadata", {
|
|
21
|
+
id: suiBcs.Address,
|
|
22
|
+
funder: suiBcs.Address,
|
|
23
|
+
spender: suiBcs.option(suiBcs.Address),
|
|
24
|
+
app: suiBcs.option(suiBcs.string())
|
|
25
|
+
});
|
|
26
|
+
function allowanceBalance({ allowance, amount, type = "0x2::sui::SUI", outputKind }) {
|
|
27
|
+
suiBcs.U64.validate(amount);
|
|
28
|
+
const objectId = normalizeSuiAddress(typeof allowance === "string" ? allowance : allowance.objectId);
|
|
29
|
+
const reference = typeof allowance === "string" ? { objectId } : allowance;
|
|
30
|
+
return (tx) => {
|
|
31
|
+
tx.addIntentResolver(ALLOWANCE_BALANCE, resolveBalances);
|
|
32
|
+
return tx.add(TransactionCommands.Intent({
|
|
33
|
+
name: ALLOWANCE_BALANCE,
|
|
34
|
+
inputs: {
|
|
35
|
+
allowance: tx.object(objectId),
|
|
36
|
+
clock: tx.object.clock(),
|
|
37
|
+
...reference.app ? { permit: tx.object(reference.app.permit) } : {}
|
|
38
|
+
},
|
|
39
|
+
data: {
|
|
40
|
+
objectId,
|
|
41
|
+
funder: reference.funder ? normalizeSuiAddress(reference.funder) : void 0,
|
|
42
|
+
appType: reference.app ? normalizeStructTag(reference.app.type) : void 0,
|
|
43
|
+
type: normalizeStructTag(type),
|
|
44
|
+
amount: String(amount),
|
|
45
|
+
outputKind
|
|
46
|
+
}
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const resolveAllowanceBalance = async (transactionData, options, next) => {
|
|
51
|
+
const ids = /* @__PURE__ */ new Set();
|
|
52
|
+
const namedTypes = /* @__PURE__ */ new Set();
|
|
53
|
+
for (const command of transactionData.commands) {
|
|
54
|
+
if (command.$kind !== "$Intent" || command.$Intent.name !== ALLOWANCE_BALANCE) continue;
|
|
55
|
+
const data = parse(AllowanceBalanceData, command.$Intent.data);
|
|
56
|
+
if (!data.funder) ids.add(data.objectId);
|
|
57
|
+
for (const type of [data.type, data.appType]) if (type && hasMvrName(type)) namedTypes.add(type);
|
|
58
|
+
}
|
|
59
|
+
const [resolvedTypes, objects] = await Promise.all([namedTypes.size ? getClient(options).core.mvr.resolve({ types: [...namedTypes] }) : void 0, ids.size ? getClient(options).core.getObjects({
|
|
60
|
+
objectIds: [...ids],
|
|
61
|
+
include: { content: true }
|
|
62
|
+
}).then((result) => result.objects) : []]);
|
|
63
|
+
const allowances = /* @__PURE__ */ new Map();
|
|
64
|
+
for (const object$1 of objects) {
|
|
65
|
+
if (object$1 instanceof Error) throw object$1;
|
|
66
|
+
allowances.set(object$1.objectId, object$1);
|
|
67
|
+
}
|
|
68
|
+
for (let index = 0; index < transactionData.commands.length; index++) {
|
|
69
|
+
const command = transactionData.commands[index];
|
|
70
|
+
if (command.$kind !== "$Intent" || command.$Intent.name !== ALLOWANCE_BALANCE) continue;
|
|
71
|
+
const data = parse(AllowanceBalanceData, command.$Intent.data);
|
|
72
|
+
if (hasMvrName(data.type)) {
|
|
73
|
+
const resolved = resolvedTypes?.types[data.type];
|
|
74
|
+
if (!resolved) throw new Error(`No resolution found for type: ${data.type}`);
|
|
75
|
+
data.type = normalizeStructTag(resolved.type);
|
|
76
|
+
}
|
|
77
|
+
if (data.appType && hasMvrName(data.appType)) {
|
|
78
|
+
const resolved = resolvedTypes?.types[data.appType];
|
|
79
|
+
if (!resolved) throw new Error(`No resolution found for type: ${data.appType}`);
|
|
80
|
+
data.appType = normalizeStructTag(resolved.type);
|
|
81
|
+
}
|
|
82
|
+
let funder = data.funder;
|
|
83
|
+
if (!funder) {
|
|
84
|
+
const allowance = allowances.get(data.objectId);
|
|
85
|
+
const expectedType = normalizeStructTag(`0x2::allowance::Allowance<0x2::balance::Balance<${data.type}>>`);
|
|
86
|
+
if (!allowance || allowance.type !== expectedType || allowance.owner.$kind !== "Shared") throw new Error(`Expected a shared ${expectedType} allowance at ${data.objectId}`);
|
|
87
|
+
const metadata = AllowanceMetadata.parse(allowance.content);
|
|
88
|
+
if (metadata.app !== null && !data.appType) throw new Error(`Allowance ${data.objectId} is app-bound; pass allowance.app with the app type and SpendPermit`);
|
|
89
|
+
if (data.appType && (metadata.app === null || normalizeStructTag(metadata.app) !== data.appType)) throw new Error(`Allowance ${data.objectId} is not bound to app ${data.appType}`);
|
|
90
|
+
funder = metadata.funder;
|
|
91
|
+
const input = command.$Intent.inputs.allowance;
|
|
92
|
+
if (input.$kind === "Input") transactionData.inputs[input.Input] = Inputs.SharedObjectRef({
|
|
93
|
+
objectId: data.objectId,
|
|
94
|
+
initialSharedVersion: allowance.owner.Shared.initialSharedVersion,
|
|
95
|
+
mutable: true
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const allowanceArgument = command.$Intent.inputs.allowance;
|
|
99
|
+
if (allowanceArgument.$kind === "Input") {
|
|
100
|
+
const input = transactionData.inputs[allowanceArgument.Input];
|
|
101
|
+
if (input.Object?.SharedObject) input.Object.SharedObject.mutable = true;
|
|
102
|
+
if (input.UnresolvedObject) input.UnresolvedObject.mutable = true;
|
|
103
|
+
}
|
|
104
|
+
const withdrawal = transactionData.addInput("withdrawal", Inputs.FundsWithdrawal({
|
|
105
|
+
reservation: {
|
|
106
|
+
$kind: "MaxAmountU64",
|
|
107
|
+
MaxAmountU64: data.amount
|
|
108
|
+
},
|
|
109
|
+
typeArg: {
|
|
110
|
+
$kind: "Balance",
|
|
111
|
+
Balance: data.type
|
|
112
|
+
},
|
|
113
|
+
withdrawFrom: {
|
|
114
|
+
$kind: "SenderAllowance",
|
|
115
|
+
SenderAllowance: {
|
|
116
|
+
funder,
|
|
117
|
+
allowance: data.objectId
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}));
|
|
121
|
+
const commands = [TransactionCommands.MoveCall({
|
|
122
|
+
target: data.appType ? "0x2::allowance::app_balance_spend" : "0x2::allowance::balance_spend",
|
|
123
|
+
typeArguments: data.appType ? [data.type, data.appType] : [data.type],
|
|
124
|
+
arguments: [
|
|
125
|
+
command.$Intent.inputs.allowance,
|
|
126
|
+
...data.appType ? [command.$Intent.inputs.permit] : [],
|
|
127
|
+
withdrawal,
|
|
128
|
+
command.$Intent.inputs.clock
|
|
129
|
+
]
|
|
130
|
+
})];
|
|
131
|
+
if (data.outputKind === "coin") commands.push(TransactionCommands.MoveCall({
|
|
132
|
+
target: "0x2::coin::from_balance",
|
|
133
|
+
typeArguments: [data.type],
|
|
134
|
+
arguments: [{
|
|
135
|
+
$kind: "Result",
|
|
136
|
+
Result: index
|
|
137
|
+
}]
|
|
138
|
+
}));
|
|
139
|
+
transactionData.replaceCommand(index, commands, { NestedResult: [index + commands.length - 1, 0] });
|
|
140
|
+
index += commands.length - 1;
|
|
141
|
+
}
|
|
142
|
+
return next();
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
export { allowanceBalance, resolveAllowanceBalance };
|
|
147
|
+
//# sourceMappingURL=AllowanceBalance.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AllowanceBalance.mjs","names":["bcs","object"],"sources":["../../../src/transactions/intents/AllowanceBalance.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { object, optional, parse, picklist, string } from 'valibot';\n\nimport { hasMvrName } from '../../client/mvr.js';\n\nimport { ALLOWANCE_BALANCE } from './BalanceIntentNames.js';\nimport { resolveBalances } from './ResolveBalances.js';\n\nimport { bcs } from '../../bcs/index.js';\nimport type { SuiClientTypes } from '../../client/index.js';\nimport { normalizeStructTag, normalizeSuiAddress } from '../../utils/sui-types.js';\nimport { TransactionCommands } from '../Commands.js';\nimport type { Argument } from '../data/internal.js';\nimport { Inputs } from '../Inputs.js';\nimport { getClient } from '../resolve.js';\nimport type { TransactionPlugin } from '../resolve.js';\nimport type { Transaction } from '../Transaction.js';\nimport type { AllowanceReference } from './BalanceOptions.js';\n\nexport { ALLOWANCE_BALANCE } from './BalanceIntentNames.js';\n\nconst AllowanceBalanceData = object({\n\tobjectId: string(),\n\tfunder: optional(string()),\n\tappType: optional(string()),\n\ttype: string(),\n\tamount: string(),\n\toutputKind: picklist(['coin', 'balance']),\n});\n\n// Read only the prefix needed for spending. The remaining settings and current_spend\n// are checked by Move, so this does not need to model rate limits or their policy.\nconst AllowanceMetadata = bcs.struct('AllowanceMetadata', {\n\tid: bcs.Address,\n\tfunder: bcs.Address,\n\tspender: bcs.option(bcs.Address),\n\tapp: bcs.option(bcs.string()),\n});\n\nexport function allowanceBalance({\n\tallowance,\n\tamount,\n\ttype = '0x2::sui::SUI',\n\toutputKind,\n}: {\n\tallowance: string | AllowanceReference;\n\tamount: bigint;\n\ttype?: string;\n\toutputKind: 'coin' | 'balance';\n}) {\n\tbcs.U64.validate(amount);\n\tconst objectId = normalizeSuiAddress(\n\t\ttypeof allowance === 'string' ? allowance : allowance.objectId,\n\t);\n\tconst reference = typeof allowance === 'string' ? { objectId } : allowance;\n\treturn (tx: Transaction) => {\n\t\ttx.addIntentResolver(ALLOWANCE_BALANCE, resolveBalances);\n\t\treturn tx.add(\n\t\t\tTransactionCommands.Intent({\n\t\t\t\tname: ALLOWANCE_BALANCE,\n\t\t\t\tinputs: {\n\t\t\t\t\tallowance: tx.object(objectId),\n\t\t\t\t\tclock: tx.object.clock(),\n\t\t\t\t\t...(reference.app ? { permit: tx.object(reference.app.permit) } : {}),\n\t\t\t\t},\n\t\t\t\tdata: {\n\t\t\t\t\tobjectId,\n\t\t\t\t\tfunder: reference.funder ? normalizeSuiAddress(reference.funder) : undefined,\n\t\t\t\t\tappType: reference.app ? normalizeStructTag(reference.app.type) : undefined,\n\t\t\t\t\ttype: normalizeStructTag(type),\n\t\t\t\t\tamount: String(amount),\n\t\t\t\t\toutputKind,\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t};\n}\n\nexport const resolveAllowanceBalance: TransactionPlugin = async (\n\ttransactionData,\n\toptions,\n\tnext,\n) => {\n\tconst ids = new Set<string>();\n\tconst namedTypes = new Set<string>();\n\tfor (const command of transactionData.commands) {\n\t\tif (command.$kind !== '$Intent' || command.$Intent.name !== ALLOWANCE_BALANCE) continue;\n\t\tconst data = parse(AllowanceBalanceData, command.$Intent.data);\n\t\tif (!data.funder) ids.add(data.objectId);\n\t\tfor (const type of [data.type, data.appType]) {\n\t\t\tif (type && hasMvrName(type)) namedTypes.add(type);\n\t\t}\n\t}\n\n\tconst [resolvedTypes, objects] = await Promise.all([\n\t\tnamedTypes.size ? getClient(options).core.mvr.resolve({ types: [...namedTypes] }) : undefined,\n\t\tids.size\n\t\t\t? getClient(options)\n\t\t\t\t\t.core.getObjects({ objectIds: [...ids], include: { content: true } })\n\t\t\t\t\t.then((result) => result.objects)\n\t\t\t: [],\n\t]);\n\tconst allowances = new Map<string, SuiClientTypes.Object<{ content: true }>>();\n\tfor (const object of objects) {\n\t\tif (object instanceof Error) throw object;\n\t\tallowances.set(object.objectId, object);\n\t}\n\n\tfor (let index = 0; index < transactionData.commands.length; index++) {\n\t\tconst command = transactionData.commands[index];\n\t\tif (command.$kind !== '$Intent' || command.$Intent.name !== ALLOWANCE_BALANCE) continue;\n\t\tconst data = parse(AllowanceBalanceData, command.$Intent.data);\n\t\tif (hasMvrName(data.type)) {\n\t\t\tconst resolved = resolvedTypes?.types[data.type];\n\t\t\tif (!resolved) throw new Error(`No resolution found for type: ${data.type}`);\n\t\t\tdata.type = normalizeStructTag(resolved.type);\n\t\t}\n\t\tif (data.appType && hasMvrName(data.appType)) {\n\t\t\tconst resolved = resolvedTypes?.types[data.appType];\n\t\t\tif (!resolved) throw new Error(`No resolution found for type: ${data.appType}`);\n\t\t\tdata.appType = normalizeStructTag(resolved.type);\n\t\t}\n\t\tlet funder = data.funder;\n\t\tif (!funder) {\n\t\t\tconst allowance = allowances.get(data.objectId);\n\t\t\tconst expectedType = normalizeStructTag(\n\t\t\t\t`0x2::allowance::Allowance<0x2::balance::Balance<${data.type}>>`,\n\t\t\t);\n\t\t\tif (!allowance || allowance.type !== expectedType || allowance.owner.$kind !== 'Shared') {\n\t\t\t\tthrow new Error(`Expected a shared ${expectedType} allowance at ${data.objectId}`);\n\t\t\t}\n\t\t\tconst metadata = AllowanceMetadata.parse(allowance.content);\n\t\t\tif (metadata.app !== null && !data.appType) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Allowance ${data.objectId} is app-bound; pass allowance.app with the app type and SpendPermit`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (\n\t\t\t\tdata.appType &&\n\t\t\t\t(metadata.app === null || normalizeStructTag(metadata.app) !== data.appType)\n\t\t\t) {\n\t\t\t\tthrow new Error(`Allowance ${data.objectId} is not bound to app ${data.appType}`);\n\t\t\t}\n\t\t\tfunder = metadata.funder;\n\t\t\tconst input = command.$Intent.inputs.allowance as Argument;\n\t\t\tif (input.$kind === 'Input') {\n\t\t\t\ttransactionData.inputs[input.Input] = Inputs.SharedObjectRef({\n\t\t\t\t\tobjectId: data.objectId,\n\t\t\t\t\tinitialSharedVersion: allowance.owner.Shared.initialSharedVersion,\n\t\t\t\t\tmutable: true,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// Spending mutates the allowance even when the caller supplied the funder\n\t\t// and we did not fetch metadata. Reuse and upgrade its existing input.\n\t\tconst allowanceArgument = command.$Intent.inputs.allowance as Argument;\n\t\tif (allowanceArgument.$kind === 'Input') {\n\t\t\tconst input = transactionData.inputs[allowanceArgument.Input];\n\t\t\tif (input.Object?.SharedObject) input.Object.SharedObject.mutable = true;\n\t\t\tif (input.UnresolvedObject) input.UnresolvedObject.mutable = true;\n\t\t}\n\t\tconst withdrawal = transactionData.addInput(\n\t\t\t'withdrawal',\n\t\t\tInputs.FundsWithdrawal({\n\t\t\t\treservation: { $kind: 'MaxAmountU64', MaxAmountU64: data.amount },\n\t\t\t\ttypeArg: { $kind: 'Balance', Balance: data.type },\n\t\t\t\twithdrawFrom: {\n\t\t\t\t\t$kind: 'SenderAllowance',\n\t\t\t\t\tSenderAllowance: { funder, allowance: data.objectId },\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\t\tconst commands = [\n\t\t\tTransactionCommands.MoveCall({\n\t\t\t\ttarget: data.appType\n\t\t\t\t\t? '0x2::allowance::app_balance_spend'\n\t\t\t\t\t: '0x2::allowance::balance_spend',\n\t\t\t\ttypeArguments: data.appType ? [data.type, data.appType] : [data.type],\n\t\t\t\targuments: [\n\t\t\t\t\tcommand.$Intent.inputs.allowance as Argument,\n\t\t\t\t\t...(data.appType ? [command.$Intent.inputs.permit as Argument] : []),\n\t\t\t\t\twithdrawal,\n\t\t\t\t\tcommand.$Intent.inputs.clock as Argument,\n\t\t\t\t],\n\t\t\t}),\n\t\t];\n\t\tif (data.outputKind === 'coin') {\n\t\t\tcommands.push(\n\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\ttarget: '0x2::coin::from_balance',\n\t\t\t\t\ttypeArguments: [data.type],\n\t\t\t\t\targuments: [{ $kind: 'Result', Result: index }],\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\ttransactionData.replaceCommand(index, commands, {\n\t\t\tNestedResult: [index + commands.length - 1, 0],\n\t\t});\n\t\tindex += commands.length - 1;\n\t}\n\treturn next();\n};\n"],"mappings":";;;;;;;;;;;AAuBA,MAAM,uBAAuB,OAAO;CACnC,UAAU,QAAQ;CAClB,QAAQ,SAAS,QAAQ,CAAC;CAC1B,SAAS,SAAS,QAAQ,CAAC;CAC3B,MAAM,QAAQ;CACd,QAAQ,QAAQ;CAChB,YAAY,SAAS,CAAC,QAAQ,UAAU,CAAC;CACzC,CAAC;AAIF,MAAM,oBAAoBA,OAAI,OAAO,qBAAqB;CACzD,IAAIA,OAAI;CACR,QAAQA,OAAI;CACZ,SAASA,OAAI,OAAOA,OAAI,QAAQ;CAChC,KAAKA,OAAI,OAAOA,OAAI,QAAQ,CAAC;CAC7B,CAAC;AAEF,SAAgB,iBAAiB,EAChC,WACA,QACA,OAAO,iBACP,cAME;AACF,QAAI,IAAI,SAAS,OAAO;CACxB,MAAM,WAAW,oBAChB,OAAO,cAAc,WAAW,YAAY,UAAU,SACtD;CACD,MAAM,YAAY,OAAO,cAAc,WAAW,EAAE,UAAU,GAAG;AACjE,SAAQ,OAAoB;AAC3B,KAAG,kBAAkB,mBAAmB,gBAAgB;AACxD,SAAO,GAAG,IACT,oBAAoB,OAAO;GAC1B,MAAM;GACN,QAAQ;IACP,WAAW,GAAG,OAAO,SAAS;IAC9B,OAAO,GAAG,OAAO,OAAO;IACxB,GAAI,UAAU,MAAM,EAAE,QAAQ,GAAG,OAAO,UAAU,IAAI,OAAO,EAAE,GAAG,EAAE;IACpE;GACD,MAAM;IACL;IACA,QAAQ,UAAU,SAAS,oBAAoB,UAAU,OAAO,GAAG;IACnE,SAAS,UAAU,MAAM,mBAAmB,UAAU,IAAI,KAAK,GAAG;IAClE,MAAM,mBAAmB,KAAK;IAC9B,QAAQ,OAAO,OAAO;IACtB;IACA;GACD,CAAC,CACF;;;AAIH,MAAa,0BAA6C,OACzD,iBACA,SACA,SACI;CACJ,MAAM,sBAAM,IAAI,KAAa;CAC7B,MAAM,6BAAa,IAAI,KAAa;AACpC,MAAK,MAAM,WAAW,gBAAgB,UAAU;AAC/C,MAAI,QAAQ,UAAU,aAAa,QAAQ,QAAQ,SAAS,kBAAmB;EAC/E,MAAM,OAAO,MAAM,sBAAsB,QAAQ,QAAQ,KAAK;AAC9D,MAAI,CAAC,KAAK,OAAQ,KAAI,IAAI,KAAK,SAAS;AACxC,OAAK,MAAM,QAAQ,CAAC,KAAK,MAAM,KAAK,QAAQ,CAC3C,KAAI,QAAQ,WAAW,KAAK,CAAE,YAAW,IAAI,KAAK;;CAIpD,MAAM,CAAC,eAAe,WAAW,MAAM,QAAQ,IAAI,CAClD,WAAW,OAAO,UAAU,QAAQ,CAAC,KAAK,IAAI,QAAQ,EAAE,OAAO,CAAC,GAAG,WAAW,EAAE,CAAC,GAAG,QACpF,IAAI,OACD,UAAU,QAAQ,CACjB,KAAK,WAAW;EAAE,WAAW,CAAC,GAAG,IAAI;EAAE,SAAS,EAAE,SAAS,MAAM;EAAE,CAAC,CACpE,MAAM,WAAW,OAAO,QAAQ,GACjC,EAAE,CACL,CAAC;CACF,MAAM,6BAAa,IAAI,KAAuD;AAC9E,MAAK,MAAMC,YAAU,SAAS;AAC7B,MAAIA,oBAAkB,MAAO,OAAMA;AACnC,aAAW,IAAIA,SAAO,UAAUA,SAAO;;AAGxC,MAAK,IAAI,QAAQ,GAAG,QAAQ,gBAAgB,SAAS,QAAQ,SAAS;EACrE,MAAM,UAAU,gBAAgB,SAAS;AACzC,MAAI,QAAQ,UAAU,aAAa,QAAQ,QAAQ,SAAS,kBAAmB;EAC/E,MAAM,OAAO,MAAM,sBAAsB,QAAQ,QAAQ,KAAK;AAC9D,MAAI,WAAW,KAAK,KAAK,EAAE;GAC1B,MAAM,WAAW,eAAe,MAAM,KAAK;AAC3C,OAAI,CAAC,SAAU,OAAM,IAAI,MAAM,iCAAiC,KAAK,OAAO;AAC5E,QAAK,OAAO,mBAAmB,SAAS,KAAK;;AAE9C,MAAI,KAAK,WAAW,WAAW,KAAK,QAAQ,EAAE;GAC7C,MAAM,WAAW,eAAe,MAAM,KAAK;AAC3C,OAAI,CAAC,SAAU,OAAM,IAAI,MAAM,iCAAiC,KAAK,UAAU;AAC/E,QAAK,UAAU,mBAAmB,SAAS,KAAK;;EAEjD,IAAI,SAAS,KAAK;AAClB,MAAI,CAAC,QAAQ;GACZ,MAAM,YAAY,WAAW,IAAI,KAAK,SAAS;GAC/C,MAAM,eAAe,mBACpB,mDAAmD,KAAK,KAAK,IAC7D;AACD,OAAI,CAAC,aAAa,UAAU,SAAS,gBAAgB,UAAU,MAAM,UAAU,SAC9E,OAAM,IAAI,MAAM,qBAAqB,aAAa,gBAAgB,KAAK,WAAW;GAEnF,MAAM,WAAW,kBAAkB,MAAM,UAAU,QAAQ;AAC3D,OAAI,SAAS,QAAQ,QAAQ,CAAC,KAAK,QAClC,OAAM,IAAI,MACT,aAAa,KAAK,SAAS,qEAC3B;AAEF,OACC,KAAK,YACJ,SAAS,QAAQ,QAAQ,mBAAmB,SAAS,IAAI,KAAK,KAAK,SAEpE,OAAM,IAAI,MAAM,aAAa,KAAK,SAAS,uBAAuB,KAAK,UAAU;AAElF,YAAS,SAAS;GAClB,MAAM,QAAQ,QAAQ,QAAQ,OAAO;AACrC,OAAI,MAAM,UAAU,QACnB,iBAAgB,OAAO,MAAM,SAAS,OAAO,gBAAgB;IAC5D,UAAU,KAAK;IACf,sBAAsB,UAAU,MAAM,OAAO;IAC7C,SAAS;IACT,CAAC;;EAKJ,MAAM,oBAAoB,QAAQ,QAAQ,OAAO;AACjD,MAAI,kBAAkB,UAAU,SAAS;GACxC,MAAM,QAAQ,gBAAgB,OAAO,kBAAkB;AACvD,OAAI,MAAM,QAAQ,aAAc,OAAM,OAAO,aAAa,UAAU;AACpE,OAAI,MAAM,iBAAkB,OAAM,iBAAiB,UAAU;;EAE9D,MAAM,aAAa,gBAAgB,SAClC,cACA,OAAO,gBAAgB;GACtB,aAAa;IAAE,OAAO;IAAgB,cAAc,KAAK;IAAQ;GACjE,SAAS;IAAE,OAAO;IAAW,SAAS,KAAK;IAAM;GACjD,cAAc;IACb,OAAO;IACP,iBAAiB;KAAE;KAAQ,WAAW,KAAK;KAAU;IACrD;GACD,CAAC,CACF;EACD,MAAM,WAAW,CAChB,oBAAoB,SAAS;GAC5B,QAAQ,KAAK,UACV,sCACA;GACH,eAAe,KAAK,UAAU,CAAC,KAAK,MAAM,KAAK,QAAQ,GAAG,CAAC,KAAK,KAAK;GACrE,WAAW;IACV,QAAQ,QAAQ,OAAO;IACvB,GAAI,KAAK,UAAU,CAAC,QAAQ,QAAQ,OAAO,OAAmB,GAAG,EAAE;IACnE;IACA,QAAQ,QAAQ,OAAO;IACvB;GACD,CAAC,CACF;AACD,MAAI,KAAK,eAAe,OACvB,UAAS,KACR,oBAAoB,SAAS;GAC5B,QAAQ;GACR,eAAe,CAAC,KAAK,KAAK;GAC1B,WAAW,CAAC;IAAE,OAAO;IAAU,QAAQ;IAAO,CAAC;GAC/C,CAAC,CACF;AAEF,kBAAgB,eAAe,OAAO,UAAU,EAC/C,cAAc,CAAC,QAAQ,SAAS,SAAS,GAAG,EAAE,EAC9C,CAAC;AACF,WAAS,SAAS,SAAS;;AAE5B,QAAO,MAAM"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/transactions/intents/BalanceIntentNames.ts
|
|
2
|
+
const ALLOWANCE_BALANCE = "AllowanceBalance";
|
|
3
|
+
const COIN_WITH_BALANCE = "CoinWithBalance";
|
|
4
|
+
|
|
5
|
+
//#endregion
|
|
6
|
+
export { ALLOWANCE_BALANCE, COIN_WITH_BALANCE };
|
|
7
|
+
//# sourceMappingURL=BalanceIntentNames.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BalanceIntentNames.mjs","names":[],"sources":["../../../src/transactions/intents/BalanceIntentNames.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nexport const ALLOWANCE_BALANCE = 'AllowanceBalance';\nexport const COIN_WITH_BALANCE = 'CoinWithBalance';\n"],"mappings":";AAGA,MAAa,oBAAoB;AACjC,MAAa,oBAAoB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TransactionObjectArgument } from "../Transaction.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/transactions/intents/BalanceOptions.d.ts
|
|
4
|
+
/** An allowance with optional funder metadata and app authorization. */
|
|
5
|
+
interface AllowanceReference {
|
|
6
|
+
objectId: string;
|
|
7
|
+
/** Skip the metadata lookup when the funder is already known. */
|
|
8
|
+
funder?: string;
|
|
9
|
+
/** Authorization for an app-bound allowance. */
|
|
10
|
+
app?: {
|
|
11
|
+
/** The app type A in SpendPermit<A>. */type: string; /** A SpendPermit<A> from the app, consumed by this spend. */
|
|
12
|
+
permit: TransactionObjectArgument;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
type BalanceOptions = {
|
|
16
|
+
/** The coin type T, not Balance<T>. Defaults to SUI. */type?: string;
|
|
17
|
+
balance: bigint | number | string;
|
|
18
|
+
} & ({
|
|
19
|
+
allowance?: never;
|
|
20
|
+
useGasCoin?: boolean;
|
|
21
|
+
} | {
|
|
22
|
+
/** An allowance ID or reference with optional app authorization. Never falls back to sender funds. */allowance: string | AllowanceReference;
|
|
23
|
+
useGasCoin?: never;
|
|
24
|
+
});
|
|
25
|
+
//#endregion
|
|
26
|
+
export { AllowanceReference, BalanceOptions };
|
|
27
|
+
//# sourceMappingURL=BalanceOptions.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BalanceOptions.d.mts","names":[],"sources":["../../../src/transactions/intents/BalanceOptions.ts"],"mappings":";;;;UAMiB,kBAAA;EAChB,QAAA;EADkC;EAGlC,MAAA;EAMkC;EAJlC,GAAA;IAFA,wCAIC,IAAA,UAAA;IAEA,MAAA,EAAQ,yBAAA;EAAA;AAAA;AAAA,KAIE,cAAA;EAAA,wDAEX,IAAA;EACA,OAAA;AAAA;EAEI,SAAA;EAAmB,UAAA;AAAA;EAAA,sGAGrB,SAAA,WAAoB,kBAAA;EACpB,UAAA;AAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/transactions/intents/BalanceOptions.ts
|
|
2
|
+
function normalizeBalance(options) {
|
|
3
|
+
if (options.allowance !== void 0 && options.useGasCoin !== void 0) throw new Error("useGasCoin cannot be combined with allowance");
|
|
4
|
+
const amount = options.balance;
|
|
5
|
+
if (typeof amount === "string" && !/^[0-9]+$/.test(amount)) throw new Error("Amount must be a non-empty string of decimal digits");
|
|
6
|
+
if (typeof amount === "number" && !Number.isSafeInteger(amount)) throw new Error("Amount must be a safe integer; use bigint or a string for larger amounts");
|
|
7
|
+
return BigInt(amount);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { normalizeBalance };
|
|
12
|
+
//# sourceMappingURL=BalanceOptions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BalanceOptions.mjs","names":[],"sources":["../../../src/transactions/intents/BalanceOptions.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { TransactionObjectArgument } from '../Transaction.js';\n\n/** An allowance with optional funder metadata and app authorization. */\nexport interface AllowanceReference {\n\tobjectId: string;\n\t/** Skip the metadata lookup when the funder is already known. */\n\tfunder?: string;\n\t/** Authorization for an app-bound allowance. */\n\tapp?: {\n\t\t/** The app type A in SpendPermit<A>. */\n\t\ttype: string;\n\t\t/** A SpendPermit<A> from the app, consumed by this spend. */\n\t\tpermit: TransactionObjectArgument;\n\t};\n}\n\nexport type BalanceOptions = {\n\t/** The coin type T, not Balance<T>. Defaults to SUI. */\n\ttype?: string;\n\tbalance: bigint | number | string;\n} & (\n\t| { allowance?: never; useGasCoin?: boolean }\n\t| {\n\t\t\t/** An allowance ID or reference with optional app authorization. Never falls back to sender funds. */\n\t\t\tallowance: string | AllowanceReference;\n\t\t\tuseGasCoin?: never;\n\t }\n);\n\nexport function normalizeBalance(options: BalanceOptions): bigint {\n\tif (options.allowance !== undefined && options.useGasCoin !== undefined) {\n\t\tthrow new Error('useGasCoin cannot be combined with allowance');\n\t}\n\tconst amount = options.balance;\n\tif (typeof amount === 'string' && !/^[0-9]+$/.test(amount)) {\n\t\tthrow new Error('Amount must be a non-empty string of decimal digits');\n\t}\n\tif (typeof amount === 'number' && !Number.isSafeInteger(amount)) {\n\t\tthrow new Error('Amount must be a safe integer; use bigint or a string for larger amounts');\n\t}\n\treturn BigInt(amount);\n}\n"],"mappings":";AAgCA,SAAgB,iBAAiB,SAAiC;AACjE,KAAI,QAAQ,cAAc,UAAa,QAAQ,eAAe,OAC7D,OAAM,IAAI,MAAM,+CAA+C;CAEhE,MAAM,SAAS,QAAQ;AACvB,KAAI,OAAO,WAAW,YAAY,CAAC,WAAW,KAAK,OAAO,CACzD,OAAM,IAAI,MAAM,sDAAsD;AAEvE,KAAI,OAAO,WAAW,YAAY,CAAC,OAAO,cAAc,OAAO,CAC9D,OAAM,IAAI,MAAM,2EAA2E;AAE5F,QAAO,OAAO,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoinWithBalance.d.mts","names":[],"sources":["../../../src/transactions/intents/CoinWithBalance.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"CoinWithBalance.d.mts","names":[],"sources":["../../../src/transactions/intents/CoinWithBalance.ts"],"mappings":";;;;;iBAkCgB,eAAA,CAAA;EACf,IAAA;EACA,OAAA;EACA;AAAA;EAEA,OAAA;EACA,IAAA;EACA,UAAA;AAAA,KACI,EAAA,EAAI,WAAA,KAAgB,iBAAA"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { normalizeStructTag } from "../../utils/sui-types.mjs";
|
|
1
|
+
import { normalizeStructTag, normalizeSuiAddress } from "../../utils/sui-types.mjs";
|
|
2
2
|
import { bcs as suiBcs } from "../../bcs/index.mjs";
|
|
3
3
|
import { TransactionCommands } from "../Commands.mjs";
|
|
4
4
|
import { Inputs } from "../Inputs.mjs";
|
|
5
|
+
import { ALLOWANCE_BALANCE, COIN_WITH_BALANCE } from "./BalanceIntentNames.mjs";
|
|
6
|
+
import { resolveBalances } from "./ResolveBalances.mjs";
|
|
5
7
|
import { bigint, integer, number, object, optional, parse, picklist, pipe, string, transform, union } from "valibot";
|
|
6
8
|
|
|
7
9
|
//#region src/transactions/intents/CoinWithBalance.ts
|
|
8
|
-
const COIN_WITH_BALANCE = "CoinWithBalance";
|
|
9
10
|
const SUI_TYPE = normalizeStructTag("0x2::sui::SUI");
|
|
10
11
|
function coinWithBalance({ type = SUI_TYPE, balance, useGasCoin = true }) {
|
|
11
12
|
let coinResult = null;
|
|
12
13
|
return (tx) => {
|
|
13
14
|
if (coinResult) return coinResult;
|
|
14
|
-
tx.addIntentResolver(COIN_WITH_BALANCE,
|
|
15
|
+
tx.addIntentResolver(COIN_WITH_BALANCE, resolveBalances);
|
|
15
16
|
const coinType = type === "gas" ? type : normalizeStructTag(type);
|
|
16
17
|
coinResult = tx.add(TransactionCommands.Intent({
|
|
17
18
|
name: COIN_WITH_BALANCE,
|
|
@@ -29,7 +30,7 @@ function createBalance({ type = SUI_TYPE, balance, useGasCoin = true }) {
|
|
|
29
30
|
let balanceResult = null;
|
|
30
31
|
return (tx) => {
|
|
31
32
|
if (balanceResult) return balanceResult;
|
|
32
|
-
tx.addIntentResolver(COIN_WITH_BALANCE,
|
|
33
|
+
tx.addIntentResolver(COIN_WITH_BALANCE, resolveBalances);
|
|
33
34
|
const coinType = type === "gas" ? type : normalizeStructTag(type);
|
|
34
35
|
balanceResult = tx.add(TransactionCommands.Intent({
|
|
35
36
|
name: COIN_WITH_BALANCE,
|
|
@@ -57,6 +58,15 @@ async function resolveCoinBalance(transactionData, buildOptions, next) {
|
|
|
57
58
|
const totalByType = /* @__PURE__ */ new Map();
|
|
58
59
|
const intentsByType = /* @__PURE__ */ new Map();
|
|
59
60
|
if (!transactionData.sender) throw new Error("Sender must be set to resolve CoinWithBalance");
|
|
61
|
+
if (transactionData.commands.some((command) => command.$Intent?.name === ALLOWANCE_BALANCE)) throw new Error("Resolve AllowanceBalance together with CoinWithBalance, or preserve both intents");
|
|
62
|
+
const reservedByType = /* @__PURE__ */ new Map();
|
|
63
|
+
for (const input of transactionData.inputs) {
|
|
64
|
+
if (!input.FundsWithdrawal) continue;
|
|
65
|
+
const { withdrawFrom, typeArg, reservation } = input.FundsWithdrawal;
|
|
66
|
+
if (normalizeSuiAddress(withdrawFrom.SenderAllowance?.funder ?? (withdrawFrom.Sender ? transactionData.sender : transactionData.gasData.owner ?? transactionData.sender)) !== normalizeSuiAddress(transactionData.sender)) continue;
|
|
67
|
+
const type = normalizeStructTag(typeArg.Balance);
|
|
68
|
+
reservedByType.set(type, (reservedByType.get(type) ?? 0n) + BigInt(reservation.MaxAmountU64));
|
|
69
|
+
}
|
|
60
70
|
for (const [i, command] of transactionData.commands.entries()) {
|
|
61
71
|
if (command.$kind !== "$Intent" || command.$Intent.name !== COIN_WITH_BALANCE) continue;
|
|
62
72
|
const { type, balance, outputKind } = parse(CoinWithBalanceData, command.$Intent.data);
|
|
@@ -94,7 +104,8 @@ async function resolveCoinBalance(transactionData, buildOptions, next) {
|
|
|
94
104
|
balance: totalByType.get(coinType),
|
|
95
105
|
client,
|
|
96
106
|
owner: transactionData.sender,
|
|
97
|
-
usedIds
|
|
107
|
+
usedIds,
|
|
108
|
+
reserved: reservedByType.get(coinType) ?? 0n
|
|
98
109
|
});
|
|
99
110
|
coinsByType.set(coinType, coins);
|
|
100
111
|
addressBalanceByType.set(coinType, addressBalance);
|
|
@@ -102,7 +113,7 @@ async function resolveCoinBalance(transactionData, buildOptions, next) {
|
|
|
102
113
|
owner: transactionData.sender,
|
|
103
114
|
coinType: SUI_TYPE
|
|
104
115
|
}).then(({ balance }) => {
|
|
105
|
-
addressBalanceByType.set("gas",
|
|
116
|
+
addressBalanceByType.set("gas", availableAddressBalance(balance.addressBalance, reservedByType.get(SUI_TYPE) ?? 0n));
|
|
106
117
|
}) : null]);
|
|
107
118
|
const exactBalanceByType = /* @__PURE__ */ new Map();
|
|
108
119
|
const usedAddressBalance = /* @__PURE__ */ new Set();
|
|
@@ -262,15 +273,20 @@ async function resolveCoinBalance(transactionData, buildOptions, next) {
|
|
|
262
273
|
}
|
|
263
274
|
return next();
|
|
264
275
|
}
|
|
265
|
-
async function getCoinsAndBalanceOfType({ coinType, balance, client, owner, usedIds }) {
|
|
276
|
+
async function getCoinsAndBalanceOfType({ coinType, balance, client, owner, usedIds, reserved }) {
|
|
266
277
|
let remainingBalance = balance;
|
|
267
278
|
const coins = [];
|
|
268
279
|
const balanceRequest = client.core.getBalance({
|
|
269
280
|
owner,
|
|
270
281
|
coinType
|
|
271
282
|
}).then(({ balance: balance$1 }) => {
|
|
272
|
-
|
|
273
|
-
|
|
283
|
+
const addressBalance = availableAddressBalance(balance$1.addressBalance, reserved);
|
|
284
|
+
remainingBalance -= addressBalance;
|
|
285
|
+
return {
|
|
286
|
+
...balance$1,
|
|
287
|
+
addressBalance: String(addressBalance),
|
|
288
|
+
balance: String(BigInt(balance$1.balance) - reserved)
|
|
289
|
+
};
|
|
274
290
|
});
|
|
275
291
|
const [allCoins, balanceResponse] = await Promise.all([loadMoreCoins(), balanceRequest]);
|
|
276
292
|
if (BigInt(balanceResponse.balance) < balance) throw new Error(`Insufficient balance of ${coinType} for owner ${owner}. Required: ${balance}, Available: ${balance - remainingBalance}`);
|
|
@@ -296,7 +312,12 @@ async function getCoinsAndBalanceOfType({ coinType, balance, client, owner, used
|
|
|
296
312
|
return coins;
|
|
297
313
|
}
|
|
298
314
|
}
|
|
315
|
+
function availableAddressBalance(balance, reserved) {
|
|
316
|
+
const available = BigInt(balance) - reserved;
|
|
317
|
+
if (available < 0n) throw new Error(`Insufficient address balance for existing withdrawals. Required: ${reserved}, Available: ${balance}`);
|
|
318
|
+
return available;
|
|
319
|
+
}
|
|
299
320
|
|
|
300
321
|
//#endregion
|
|
301
|
-
export {
|
|
322
|
+
export { coinWithBalance, createBalance, resolveCoinBalance };
|
|
302
323
|
//# sourceMappingURL=CoinWithBalance.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoinWithBalance.mjs","names":["bcs","balance"],"sources":["../../../src/transactions/intents/CoinWithBalance.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { InferInput } from 'valibot';\nimport {\n\tbigint,\n\tinteger,\n\tnumber,\n\tobject,\n\toptional,\n\tparse,\n\tpicklist,\n\tpipe,\n\tstring,\n\ttransform,\n\tunion,\n} from 'valibot';\n\nimport { bcs } from '../../bcs/index.js';\nimport { normalizeStructTag } from '../../utils/sui-types.js';\nimport { TransactionCommands } from '../Commands.js';\nimport type { Argument } from '../data/internal.js';\nimport { Inputs } from '../Inputs.js';\nimport type { BuildTransactionOptions } from '../resolve.js';\nimport type { Transaction, TransactionResult } from '../Transaction.js';\nimport type { TransactionDataBuilder } from '../TransactionData.js';\nimport type { ClientWithCoreApi, SuiClientTypes } from '../../client/index.js';\n\nexport const COIN_WITH_BALANCE = 'CoinWithBalance';\nconst SUI_TYPE = normalizeStructTag('0x2::sui::SUI');\n\nexport function coinWithBalance({\n\ttype = SUI_TYPE,\n\tbalance,\n\tuseGasCoin = true,\n}: {\n\tbalance: bigint | number;\n\ttype?: string;\n\tuseGasCoin?: boolean;\n}): (tx: Transaction) => TransactionResult {\n\tlet coinResult: TransactionResult | null = null;\n\n\treturn (tx: Transaction) => {\n\t\tif (coinResult) {\n\t\t\treturn coinResult;\n\t\t}\n\n\t\ttx.addIntentResolver(COIN_WITH_BALANCE, resolveCoinBalance);\n\t\tconst coinType = type === 'gas' ? type : normalizeStructTag(type);\n\n\t\tcoinResult = tx.add(\n\t\t\tTransactionCommands.Intent({\n\t\t\t\tname: COIN_WITH_BALANCE,\n\t\t\t\tinputs: {},\n\t\t\t\tdata: {\n\t\t\t\t\ttype: coinType === SUI_TYPE && useGasCoin ? 'gas' : coinType,\n\t\t\t\t\tbalance: BigInt(balance),\n\t\t\t\t\toutputKind: 'coin',\n\t\t\t\t} satisfies InferInput<typeof CoinWithBalanceData>,\n\t\t\t}),\n\t\t);\n\n\t\treturn coinResult;\n\t};\n}\n\nexport function createBalance({\n\ttype = SUI_TYPE,\n\tbalance,\n\tuseGasCoin = true,\n}: {\n\tbalance: bigint | number;\n\ttype?: string;\n\tuseGasCoin?: boolean;\n}): (tx: Transaction) => TransactionResult {\n\tlet balanceResult: TransactionResult | null = null;\n\n\treturn (tx: Transaction) => {\n\t\tif (balanceResult) {\n\t\t\treturn balanceResult;\n\t\t}\n\n\t\ttx.addIntentResolver(COIN_WITH_BALANCE, resolveCoinBalance);\n\t\tconst coinType = type === 'gas' ? type : normalizeStructTag(type);\n\n\t\tbalanceResult = tx.add(\n\t\t\tTransactionCommands.Intent({\n\t\t\t\tname: COIN_WITH_BALANCE,\n\t\t\t\tinputs: {},\n\t\t\t\tdata: {\n\t\t\t\t\ttype: coinType === SUI_TYPE && useGasCoin ? 'gas' : coinType,\n\t\t\t\t\tbalance: BigInt(balance),\n\t\t\t\t\toutputKind: 'balance',\n\t\t\t\t} satisfies InferInput<typeof CoinWithBalanceData>,\n\t\t\t}),\n\t\t);\n\n\t\treturn balanceResult;\n\t};\n}\n\n// `balance` is a bigint in memory, but serializing a transaction to JSON converts it to a\n// string. When that JSON is deserialized with `Transaction.from`, the value stays a string\n// (the intent `data` is opaque to the transaction schema), so coerce it back to a bigint here.\nconst CoinWithBalanceData = object({\n\ttype: string(),\n\tbalance: pipe(\n\t\tunion([bigint(), string(), pipe(number(), integer())]),\n\t\ttransform((value) => BigInt(value)),\n\t),\n\toutputKind: optional(picklist(['coin', 'balance'])),\n});\n\nexport async function resolveCoinBalance(\n\ttransactionData: TransactionDataBuilder,\n\tbuildOptions: BuildTransactionOptions,\n\tnext: () => Promise<void>,\n) {\n\ttype IntentInfo = { balance: bigint; outputKind: 'coin' | 'balance' };\n\n\tconst coinTypes = new Set<string>();\n\tconst totalByType = new Map<string, bigint>();\n\tconst intentsByType = new Map<string, IntentInfo[]>();\n\n\tif (!transactionData.sender) {\n\t\tthrow new Error('Sender must be set to resolve CoinWithBalance');\n\t}\n\n\t// First pass: scan intents, collect per-type data, and resolve zero-balance intents in place.\n\tfor (const [i, command] of transactionData.commands.entries()) {\n\t\tif (command.$kind !== '$Intent' || command.$Intent.name !== COIN_WITH_BALANCE) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { type, balance, outputKind } = parse(CoinWithBalanceData, command.$Intent.data);\n\n\t\t// Zero-balance intents are resolved immediately — no coins or AB needed.\n\t\t// This is a 1:1 replacement so indices don't shift.\n\t\tif (balance === 0n) {\n\t\t\tconst coinType = type === 'gas' ? SUI_TYPE : type;\n\t\t\ttransactionData.replaceCommand(\n\t\t\t\ti,\n\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\ttarget: (outputKind ?? 'coin') === 'balance' ? '0x2::balance::zero' : '0x2::coin::zero',\n\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (type !== 'gas') {\n\t\t\tcoinTypes.add(type);\n\t\t}\n\n\t\ttotalByType.set(type, (totalByType.get(type) ?? 0n) + balance);\n\n\t\tif (!intentsByType.has(type)) intentsByType.set(type, []);\n\t\tintentsByType.get(type)!.push({ balance, outputKind: outputKind ?? 'coin' });\n\t}\n\n\tif (totalByType.has('gas') && totalByType.has(SUI_TYPE)) {\n\t\tthrow new Error(\n\t\t\t'Cannot mix SUI CoinWithBalance intents that use the gas coin with ones that do not (useGasCoin: false). Use one or the other.',\n\t\t);\n\t}\n\n\tconst usedIds = new Set<string>();\n\n\tfor (const input of transactionData.inputs) {\n\t\tif (input.Object?.ImmOrOwnedObject) {\n\t\t\tusedIds.add(input.Object.ImmOrOwnedObject.objectId);\n\t\t}\n\t\tif (input.UnresolvedObject?.objectId) {\n\t\t\tusedIds.add(input.UnresolvedObject.objectId);\n\t\t}\n\t}\n\n\tconst coinsByType = new Map<string, SuiClientTypes.Coin[]>();\n\tconst addressBalanceByType = new Map<string, bigint>();\n\tconst client = buildOptions.client;\n\tconst assumeSufficientAddressBalances = buildOptions.assumeSufficientAddressBalances;\n\n\tif (!client && !assumeSufficientAddressBalances) {\n\t\tthrow new Error(\n\t\t\t'Client must be provided to build or serialize transactions with CoinWithBalance intents',\n\t\t);\n\t}\n\n\tif (assumeSufficientAddressBalances) {\n\t\tfor (const [coinType, balance] of totalByType) {\n\t\t\taddressBalanceByType.set(coinType, balance);\n\t\t}\n\t} else {\n\t\tawait Promise.all([\n\t\t\t...[...coinTypes].map(async (coinType) => {\n\t\t\t\tconst { coins, addressBalance } = await getCoinsAndBalanceOfType({\n\t\t\t\t\tcoinType,\n\t\t\t\t\tbalance: totalByType.get(coinType)!,\n\t\t\t\t\tclient: client!,\n\t\t\t\t\towner: transactionData.sender!,\n\t\t\t\t\tusedIds,\n\t\t\t\t});\n\n\t\t\t\tcoinsByType.set(coinType, coins);\n\t\t\t\taddressBalanceByType.set(coinType, addressBalance);\n\t\t\t}),\n\t\t\ttotalByType.has('gas')\n\t\t\t\t? await client!.core\n\t\t\t\t\t\t.getBalance({\n\t\t\t\t\t\t\towner: transactionData.sender!,\n\t\t\t\t\t\t\tcoinType: SUI_TYPE,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.then(({ balance }) => {\n\t\t\t\t\t\t\taddressBalanceByType.set('gas', BigInt(balance.addressBalance));\n\t\t\t\t\t\t})\n\t\t\t\t: null,\n\t\t]);\n\t}\n\n\tconst exactBalanceByType = new Map<string, boolean>();\n\tconst usedAddressBalance = new Set<string>();\n\n\t// Per-type state for Path 2 combined splits\n\ttype TypeState = { results: Argument[]; nextIntent: number };\n\tconst typeState = new Map<string, TypeState>();\n\n\tlet index = 0;\n\twhile (index < transactionData.commands.length) {\n\t\tconst transaction = transactionData.commands[index];\n\t\tif (transaction.$kind !== '$Intent' || transaction.$Intent.name !== COIN_WITH_BALANCE) {\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { type, balance } = parse(CoinWithBalanceData, transaction.$Intent.data);\n\t\tconst coinType = type === 'gas' ? SUI_TYPE : type;\n\t\tconst totalRequired = totalByType.get(type)!;\n\t\tconst addressBalance = addressBalanceByType.get(type) ?? 0n;\n\n\t\tconst commands = [];\n\t\tlet intentResult: Argument;\n\n\t\tconst intentsForType = intentsByType.get(type) ?? [];\n\t\tconst allBalance = intentsForType.every((i) => i.outputKind === 'balance');\n\n\t\tif (allBalance && addressBalance >= totalRequired) {\n\t\t\t// Path 1: All balance intents and AB sufficient — direct per-intent withdrawal.\n\t\t\t// No coins touched, enables parallel execution.\n\t\t\tcommands.push(\n\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\ttarget: '0x2::balance::redeem_funds',\n\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\targuments: [\n\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t'withdrawal',\n\t\t\t\t\t\t\tInputs.FundsWithdrawal({\n\t\t\t\t\t\t\t\treservation: {\n\t\t\t\t\t\t\t\t\t$kind: 'MaxAmountU64',\n\t\t\t\t\t\t\t\t\tMaxAmountU64: String(balance),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttypeArg: { $kind: 'Balance', Balance: coinType },\n\t\t\t\t\t\t\t\twithdrawFrom: { $kind: 'Sender', Sender: true },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tintentResult = {\n\t\t\t\t$kind: 'NestedResult',\n\t\t\t\tNestedResult: [index + commands.length - 1, 0],\n\t\t\t};\n\t\t} else {\n\t\t\t// Path 2: Merge and Split — build a merged coin, split all intents at once.\n\n\t\t\tif (!typeState.has(type)) {\n\t\t\t\tconst intents = intentsForType;\n\n\t\t\t\t// Step 1: Build sources and merge\n\t\t\t\tconst sources: Argument[] = [];\n\n\t\t\t\tif (addressBalance >= totalRequired) {\n\t\t\t\t\t// AB sufficient — source entirely from address balance, no coins needed.\n\t\t\t\t\tusedAddressBalance.add(type);\n\n\t\t\t\t\tcommands.push(\n\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\ttarget: '0x2::coin::redeem_funds',\n\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t\t'withdrawal',\n\t\t\t\t\t\t\t\t\tInputs.FundsWithdrawal({\n\t\t\t\t\t\t\t\t\t\treservation: {\n\t\t\t\t\t\t\t\t\t\t\t$kind: 'MaxAmountU64',\n\t\t\t\t\t\t\t\t\t\t\tMaxAmountU64: String(totalRequired),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\ttypeArg: { $kind: 'Balance', Balance: coinType },\n\t\t\t\t\t\t\t\t\t\twithdrawFrom: { $kind: 'Sender', Sender: true },\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tsources.push({ $kind: 'Result', Result: index + commands.length - 1 });\n\t\t\t\t} else if (type === 'gas') {\n\t\t\t\t\tsources.push({ $kind: 'GasCoin', GasCoin: true });\n\t\t\t\t} else {\n\t\t\t\t\tconst coins = coinsByType.get(type)!;\n\t\t\t\t\tconst loadedCoinBalance = coins.reduce((sum, c) => sum + BigInt(c.balance), 0n);\n\t\t\t\t\tconst abNeeded =\n\t\t\t\t\t\ttotalRequired > loadedCoinBalance ? totalRequired - loadedCoinBalance : 0n;\n\n\t\t\t\t\texactBalanceByType.set(type, loadedCoinBalance + abNeeded === totalRequired);\n\n\t\t\t\t\tfor (const coin of coins) {\n\t\t\t\t\t\tsources.push(\n\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t'object',\n\t\t\t\t\t\t\t\tInputs.ObjectRef({\n\t\t\t\t\t\t\t\t\tobjectId: coin.objectId,\n\t\t\t\t\t\t\t\t\tdigest: coin.digest,\n\t\t\t\t\t\t\t\t\tversion: coin.version,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (abNeeded > 0n) {\n\t\t\t\t\t\tusedAddressBalance.add(type);\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::redeem_funds',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t\t\t'withdrawal',\n\t\t\t\t\t\t\t\t\t\tInputs.FundsWithdrawal({\n\t\t\t\t\t\t\t\t\t\t\treservation: {\n\t\t\t\t\t\t\t\t\t\t\t\t$kind: 'MaxAmountU64',\n\t\t\t\t\t\t\t\t\t\t\t\tMaxAmountU64: String(abNeeded),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttypeArg: { $kind: 'Balance', Balance: coinType },\n\t\t\t\t\t\t\t\t\t\t\twithdrawFrom: { $kind: 'Sender', Sender: true },\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsources.push({ $kind: 'Result', Result: index + commands.length - 1 });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst baseCoin = sources[0];\n\t\t\t\tconst rest = sources.slice(1);\n\t\t\t\tfor (let i = 0; i < rest.length; i += 500) {\n\t\t\t\t\tcommands.push(TransactionCommands.MergeCoins(baseCoin, rest.slice(i, i + 500)));\n\t\t\t\t}\n\n\t\t\t\t// Step 2: Combined SplitCoins for all intents of this type\n\t\t\t\tconst splitCmdIndex = index + commands.length;\n\t\t\t\tcommands.push(\n\t\t\t\t\tTransactionCommands.SplitCoins(\n\t\t\t\t\t\tbaseCoin,\n\t\t\t\t\t\tintents.map((i) =>\n\t\t\t\t\t\t\ttransactionData.addInput('pure', Inputs.Pure(bcs.u64().serialize(i.balance))),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\t// Build per-intent results, adding into_balance conversions for balance intents\n\t\t\t\tconst results: Argument[] = [];\n\t\t\t\tfor (let i = 0; i < intents.length; i++) {\n\t\t\t\t\tconst splitResult: Argument = {\n\t\t\t\t\t\t$kind: 'NestedResult',\n\t\t\t\t\t\tNestedResult: [splitCmdIndex, i],\n\t\t\t\t\t};\n\n\t\t\t\t\tif (intents[i].outputKind === 'balance') {\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::into_balance',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [splitResult],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tresults.push({\n\t\t\t\t\t\t\t$kind: 'NestedResult',\n\t\t\t\t\t\t\tNestedResult: [index + commands.length - 1, 0],\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.push(splitResult);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Step 3: Remainder handling\n\t\t\t\t//\n\t\t\t\t// Add cleanup to this replacement command list rather than appending\n\t\t\t\t// it to the complete transaction. Appending cleanup can place it after\n\t\t\t\t// a MoveCall that consumes Random, which Sui rejects.\n\t\t\t\t//\n\t\t\t\t// When gas type used GasCoin (not AB), leftover stays in the gas coin\n\t\t\t\t// -- no remainder handling is needed.\n\t\t\t\tif (type !== 'gas' || usedAddressBalance.has(type)) {\n\t\t\t\t\tconst hasBalanceIntent = intents.some((intent) => intent.outputKind === 'balance');\n\t\t\t\t\tconst sourcedFromAB = usedAddressBalance.has(type);\n\n\t\t\t\t\tif (hasBalanceIntent || sourcedFromAB) {\n\t\t\t\t\t\t// Sourced from AB or balance intents exist: send remainder back to sender's address\n\t\t\t\t\t\t// balance. `coin::send_funds` is gasless-eligible and handles zero amounts.\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::send_funds',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\t\tbaseCoin,\n\t\t\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t\t\t'pure',\n\t\t\t\t\t\t\t\t\t\tInputs.Pure(bcs.Address.serialize(transactionData.sender!)),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (exactBalanceByType.get(type)) {\n\t\t\t\t\t\t// Coin-only with exact match: destroy the zero-value dust coin.\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::destroy_zero',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [baseCoin],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// Coin-only with surplus: merged coin stays with sender as an owned object.\n\t\t\t\t}\n\n\t\t\t\ttypeState.set(type, { results, nextIntent: 0 });\n\t\t\t}\n\n\t\t\tconst state = typeState.get(type)!;\n\t\t\tintentResult = state.results[state.nextIntent++];\n\t\t}\n\n\t\ttransactionData.replaceCommand(\n\t\t\tindex,\n\t\t\tcommands,\n\t\t\tintentResult as { NestedResult: [number, number] },\n\t\t);\n\n\t\t// Advance past the replacement. When commands is empty (subsequent intents\n\t\t// of a combined split), the command was removed and the next command shifted\n\t\t// into this position — so we stay at the same index.\n\t\tindex += commands.length;\n\t}\n\n\treturn next();\n}\n\nasync function getCoinsAndBalanceOfType({\n\tcoinType,\n\tbalance,\n\tclient,\n\towner,\n\tusedIds,\n}: {\n\tcoinType: string;\n\tbalance: bigint;\n\tclient: ClientWithCoreApi;\n\towner: string;\n\tusedIds: Set<string>;\n}): Promise<{\n\tcoins: SuiClientTypes.Coin[];\n\tbalance: bigint;\n\taddressBalance: bigint;\n\tcoinBalance: bigint;\n}> {\n\tlet remainingBalance = balance;\n\tconst coins: SuiClientTypes.Coin[] = [];\n\tconst balanceRequest = client.core.getBalance({ owner, coinType }).then(({ balance }) => {\n\t\tremainingBalance -= BigInt(balance.addressBalance);\n\n\t\treturn balance;\n\t});\n\n\tconst [allCoins, balanceResponse] = await Promise.all([loadMoreCoins(), balanceRequest]);\n\n\tif (BigInt(balanceResponse.balance) < balance) {\n\t\tthrow new Error(\n\t\t\t`Insufficient balance of ${coinType} for owner ${owner}. Required: ${balance}, Available: ${\n\t\t\t\tbalance - remainingBalance\n\t\t\t}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tcoins: allCoins,\n\t\tbalance: BigInt(balanceResponse.coinBalance),\n\t\taddressBalance: BigInt(balanceResponse.addressBalance),\n\t\tcoinBalance: BigInt(balanceResponse.coinBalance),\n\t};\n\n\tasync function loadMoreCoins(cursor: string | null = null): Promise<SuiClientTypes.Coin[]> {\n\t\tconst {\n\t\t\tobjects,\n\t\t\thasNextPage,\n\t\t\tcursor: nextCursor,\n\t\t} = await client.core.listCoins({\n\t\t\towner,\n\t\t\tcoinType,\n\t\t\tcursor,\n\t\t});\n\n\t\tawait balanceRequest;\n\n\t\t// Always load all coins from the page (except already-used ones).\n\t\t// This merges all available coins rather than leaving dust.\n\t\tfor (const coin of objects) {\n\t\t\tif (usedIds.has(coin.objectId)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcoins.push(coin);\n\t\t\tremainingBalance -= BigInt(coin.balance);\n\t\t}\n\n\t\t// Only paginate if loaded coins + AB are still insufficient\n\t\tif (remainingBalance > 0n && hasNextPage) {\n\t\t\treturn loadMoreCoins(nextCursor);\n\t\t}\n\n\t\treturn coins;\n\t}\n}\n"],"mappings":";;;;;;;AA4BA,MAAa,oBAAoB;AACjC,MAAM,WAAW,mBAAmB,gBAAgB;AAEpD,SAAgB,gBAAgB,EAC/B,OAAO,UACP,SACA,aAAa,QAK6B;CAC1C,IAAI,aAAuC;AAE3C,SAAQ,OAAoB;AAC3B,MAAI,WACH,QAAO;AAGR,KAAG,kBAAkB,mBAAmB,mBAAmB;EAC3D,MAAM,WAAW,SAAS,QAAQ,OAAO,mBAAmB,KAAK;AAEjE,eAAa,GAAG,IACf,oBAAoB,OAAO;GAC1B,MAAM;GACN,QAAQ,EAAE;GACV,MAAM;IACL,MAAM,aAAa,YAAY,aAAa,QAAQ;IACpD,SAAS,OAAO,QAAQ;IACxB,YAAY;IACZ;GACD,CAAC,CACF;AAED,SAAO;;;AAIT,SAAgB,cAAc,EAC7B,OAAO,UACP,SACA,aAAa,QAK6B;CAC1C,IAAI,gBAA0C;AAE9C,SAAQ,OAAoB;AAC3B,MAAI,cACH,QAAO;AAGR,KAAG,kBAAkB,mBAAmB,mBAAmB;EAC3D,MAAM,WAAW,SAAS,QAAQ,OAAO,mBAAmB,KAAK;AAEjE,kBAAgB,GAAG,IAClB,oBAAoB,OAAO;GAC1B,MAAM;GACN,QAAQ,EAAE;GACV,MAAM;IACL,MAAM,aAAa,YAAY,aAAa,QAAQ;IACpD,SAAS,OAAO,QAAQ;IACxB,YAAY;IACZ;GACD,CAAC,CACF;AAED,SAAO;;;AAOT,MAAM,sBAAsB,OAAO;CAClC,MAAM,QAAQ;CACd,SAAS,KACR,MAAM;EAAC,QAAQ;EAAE,QAAQ;EAAE,KAAK,QAAQ,EAAE,SAAS,CAAC;EAAC,CAAC,EACtD,WAAW,UAAU,OAAO,MAAM,CAAC,CACnC;CACD,YAAY,SAAS,SAAS,CAAC,QAAQ,UAAU,CAAC,CAAC;CACnD,CAAC;AAEF,eAAsB,mBACrB,iBACA,cACA,MACC;CAGD,MAAM,4BAAY,IAAI,KAAa;CACnC,MAAM,8BAAc,IAAI,KAAqB;CAC7C,MAAM,gCAAgB,IAAI,KAA2B;AAErD,KAAI,CAAC,gBAAgB,OACpB,OAAM,IAAI,MAAM,gDAAgD;AAIjE,MAAK,MAAM,CAAC,GAAG,YAAY,gBAAgB,SAAS,SAAS,EAAE;AAC9D,MAAI,QAAQ,UAAU,aAAa,QAAQ,QAAQ,SAAS,kBAC3D;EAGD,MAAM,EAAE,MAAM,SAAS,eAAe,MAAM,qBAAqB,QAAQ,QAAQ,KAAK;AAItF,MAAI,YAAY,IAAI;GACnB,MAAM,WAAW,SAAS,QAAQ,WAAW;AAC7C,mBAAgB,eACf,GACA,oBAAoB,SAAS;IAC5B,SAAS,cAAc,YAAY,YAAY,uBAAuB;IACtE,eAAe,CAAC,SAAS;IACzB,CAAC,CACF;AACD;;AAGD,MAAI,SAAS,MACZ,WAAU,IAAI,KAAK;AAGpB,cAAY,IAAI,OAAO,YAAY,IAAI,KAAK,IAAI,MAAM,QAAQ;AAE9D,MAAI,CAAC,cAAc,IAAI,KAAK,CAAE,eAAc,IAAI,MAAM,EAAE,CAAC;AACzD,gBAAc,IAAI,KAAK,CAAE,KAAK;GAAE;GAAS,YAAY,cAAc;GAAQ,CAAC;;AAG7E,KAAI,YAAY,IAAI,MAAM,IAAI,YAAY,IAAI,SAAS,CACtD,OAAM,IAAI,MACT,gIACA;CAGF,MAAM,0BAAU,IAAI,KAAa;AAEjC,MAAK,MAAM,SAAS,gBAAgB,QAAQ;AAC3C,MAAI,MAAM,QAAQ,iBACjB,SAAQ,IAAI,MAAM,OAAO,iBAAiB,SAAS;AAEpD,MAAI,MAAM,kBAAkB,SAC3B,SAAQ,IAAI,MAAM,iBAAiB,SAAS;;CAI9C,MAAM,8BAAc,IAAI,KAAoC;CAC5D,MAAM,uCAAuB,IAAI,KAAqB;CACtD,MAAM,SAAS,aAAa;CAC5B,MAAM,kCAAkC,aAAa;AAErD,KAAI,CAAC,UAAU,CAAC,gCACf,OAAM,IAAI,MACT,0FACA;AAGF,KAAI,gCACH,MAAK,MAAM,CAAC,UAAU,YAAY,YACjC,sBAAqB,IAAI,UAAU,QAAQ;KAG5C,OAAM,QAAQ,IAAI,CACjB,GAAG,CAAC,GAAG,UAAU,CAAC,IAAI,OAAO,aAAa;EACzC,MAAM,EAAE,OAAO,mBAAmB,MAAM,yBAAyB;GAChE;GACA,SAAS,YAAY,IAAI,SAAS;GAC1B;GACR,OAAO,gBAAgB;GACvB;GACA,CAAC;AAEF,cAAY,IAAI,UAAU,MAAM;AAChC,uBAAqB,IAAI,UAAU,eAAe;GACjD,EACF,YAAY,IAAI,MAAM,GACnB,MAAM,OAAQ,KACb,WAAW;EACX,OAAO,gBAAgB;EACvB,UAAU;EACV,CAAC,CACD,MAAM,EAAE,cAAc;AACtB,uBAAqB,IAAI,OAAO,OAAO,QAAQ,eAAe,CAAC;GAC9D,GACF,KACH,CAAC;CAGH,MAAM,qCAAqB,IAAI,KAAsB;CACrD,MAAM,qCAAqB,IAAI,KAAa;CAI5C,MAAM,4BAAY,IAAI,KAAwB;CAE9C,IAAI,QAAQ;AACZ,QAAO,QAAQ,gBAAgB,SAAS,QAAQ;EAC/C,MAAM,cAAc,gBAAgB,SAAS;AAC7C,MAAI,YAAY,UAAU,aAAa,YAAY,QAAQ,SAAS,mBAAmB;AACtF;AACA;;EAGD,MAAM,EAAE,MAAM,YAAY,MAAM,qBAAqB,YAAY,QAAQ,KAAK;EAC9E,MAAM,WAAW,SAAS,QAAQ,WAAW;EAC7C,MAAM,gBAAgB,YAAY,IAAI,KAAK;EAC3C,MAAM,iBAAiB,qBAAqB,IAAI,KAAK,IAAI;EAEzD,MAAM,WAAW,EAAE;EACnB,IAAI;EAEJ,MAAM,iBAAiB,cAAc,IAAI,KAAK,IAAI,EAAE;AAGpD,MAFmB,eAAe,OAAO,MAAM,EAAE,eAAe,UAAU,IAExD,kBAAkB,eAAe;AAGlD,YAAS,KACR,oBAAoB,SAAS;IAC5B,QAAQ;IACR,eAAe,CAAC,SAAS;IACzB,WAAW,CACV,gBAAgB,SACf,cACA,OAAO,gBAAgB;KACtB,aAAa;MACZ,OAAO;MACP,cAAc,OAAO,QAAQ;MAC7B;KACD,SAAS;MAAE,OAAO;MAAW,SAAS;MAAU;KAChD,cAAc;MAAE,OAAO;MAAU,QAAQ;MAAM;KAC/C,CAAC,CACF,CACD;IACD,CAAC,CACF;AAED,kBAAe;IACd,OAAO;IACP,cAAc,CAAC,QAAQ,SAAS,SAAS,GAAG,EAAE;IAC9C;SACK;AAGN,OAAI,CAAC,UAAU,IAAI,KAAK,EAAE;IACzB,MAAM,UAAU;IAGhB,MAAM,UAAsB,EAAE;AAE9B,QAAI,kBAAkB,eAAe;AAEpC,wBAAmB,IAAI,KAAK;AAE5B,cAAS,KACR,oBAAoB,SAAS;MAC5B,QAAQ;MACR,eAAe,CAAC,SAAS;MACzB,WAAW,CACV,gBAAgB,SACf,cACA,OAAO,gBAAgB;OACtB,aAAa;QACZ,OAAO;QACP,cAAc,OAAO,cAAc;QACnC;OACD,SAAS;QAAE,OAAO;QAAW,SAAS;QAAU;OAChD,cAAc;QAAE,OAAO;QAAU,QAAQ;QAAM;OAC/C,CAAC,CACF,CACD;MACD,CAAC,CACF;AACD,aAAQ,KAAK;MAAE,OAAO;MAAU,QAAQ,QAAQ,SAAS,SAAS;MAAG,CAAC;eAC5D,SAAS,MACnB,SAAQ,KAAK;KAAE,OAAO;KAAW,SAAS;KAAM,CAAC;SAC3C;KACN,MAAM,QAAQ,YAAY,IAAI,KAAK;KACnC,MAAM,oBAAoB,MAAM,QAAQ,KAAK,MAAM,MAAM,OAAO,EAAE,QAAQ,EAAE,GAAG;KAC/E,MAAM,WACL,gBAAgB,oBAAoB,gBAAgB,oBAAoB;AAEzE,wBAAmB,IAAI,MAAM,oBAAoB,aAAa,cAAc;AAE5E,UAAK,MAAM,QAAQ,MAClB,SAAQ,KACP,gBAAgB,SACf,UACA,OAAO,UAAU;MAChB,UAAU,KAAK;MACf,QAAQ,KAAK;MACb,SAAS,KAAK;MACd,CAAC,CACF,CACD;AAGF,SAAI,WAAW,IAAI;AAClB,yBAAmB,IAAI,KAAK;AAC5B,eAAS,KACR,oBAAoB,SAAS;OAC5B,QAAQ;OACR,eAAe,CAAC,SAAS;OACzB,WAAW,CACV,gBAAgB,SACf,cACA,OAAO,gBAAgB;QACtB,aAAa;SACZ,OAAO;SACP,cAAc,OAAO,SAAS;SAC9B;QACD,SAAS;SAAE,OAAO;SAAW,SAAS;SAAU;QAChD,cAAc;SAAE,OAAO;SAAU,QAAQ;SAAM;QAC/C,CAAC,CACF,CACD;OACD,CAAC,CACF;AACD,cAAQ,KAAK;OAAE,OAAO;OAAU,QAAQ,QAAQ,SAAS,SAAS;OAAG,CAAC;;;IAIxE,MAAM,WAAW,QAAQ;IACzB,MAAM,OAAO,QAAQ,MAAM,EAAE;AAC7B,SAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,IACrC,UAAS,KAAK,oBAAoB,WAAW,UAAU,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,CAAC;IAIhF,MAAM,gBAAgB,QAAQ,SAAS;AACvC,aAAS,KACR,oBAAoB,WACnB,UACA,QAAQ,KAAK,MACZ,gBAAgB,SAAS,QAAQ,OAAO,KAAKA,OAAI,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAC7E,CACD,CACD;IAGD,MAAM,UAAsB,EAAE;AAC9B,SAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;KACxC,MAAM,cAAwB;MAC7B,OAAO;MACP,cAAc,CAAC,eAAe,EAAE;MAChC;AAED,SAAI,QAAQ,GAAG,eAAe,WAAW;AACxC,eAAS,KACR,oBAAoB,SAAS;OAC5B,QAAQ;OACR,eAAe,CAAC,SAAS;OACzB,WAAW,CAAC,YAAY;OACxB,CAAC,CACF;AACD,cAAQ,KAAK;OACZ,OAAO;OACP,cAAc,CAAC,QAAQ,SAAS,SAAS,GAAG,EAAE;OAC9C,CAAC;WAEF,SAAQ,KAAK,YAAY;;AAY3B,QAAI,SAAS,SAAS,mBAAmB,IAAI,KAAK,EAAE;KACnD,MAAM,mBAAmB,QAAQ,MAAM,WAAW,OAAO,eAAe,UAAU;KAClF,MAAM,gBAAgB,mBAAmB,IAAI,KAAK;AAElD,SAAI,oBAAoB,cAGvB,UAAS,KACR,oBAAoB,SAAS;MAC5B,QAAQ;MACR,eAAe,CAAC,SAAS;MACzB,WAAW,CACV,UACA,gBAAgB,SACf,QACA,OAAO,KAAKA,OAAI,QAAQ,UAAU,gBAAgB,OAAQ,CAAC,CAC3D,CACD;MACD,CAAC,CACF;cACS,mBAAmB,IAAI,KAAK,CAEtC,UAAS,KACR,oBAAoB,SAAS;MAC5B,QAAQ;MACR,eAAe,CAAC,SAAS;MACzB,WAAW,CAAC,SAAS;MACrB,CAAC,CACF;;AAKH,cAAU,IAAI,MAAM;KAAE;KAAS,YAAY;KAAG,CAAC;;GAGhD,MAAM,QAAQ,UAAU,IAAI,KAAK;AACjC,kBAAe,MAAM,QAAQ,MAAM;;AAGpC,kBAAgB,eACf,OACA,UACA,aACA;AAKD,WAAS,SAAS;;AAGnB,QAAO,MAAM;;AAGd,eAAe,yBAAyB,EACvC,UACA,SACA,QACA,OACA,WAYE;CACF,IAAI,mBAAmB;CACvB,MAAM,QAA+B,EAAE;CACvC,MAAM,iBAAiB,OAAO,KAAK,WAAW;EAAE;EAAO;EAAU,CAAC,CAAC,MAAM,EAAE,yBAAc;AACxF,sBAAoB,OAAOC,UAAQ,eAAe;AAElD,SAAOA;GACN;CAEF,MAAM,CAAC,UAAU,mBAAmB,MAAM,QAAQ,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC;AAExF,KAAI,OAAO,gBAAgB,QAAQ,GAAG,QACrC,OAAM,IAAI,MACT,2BAA2B,SAAS,aAAa,MAAM,cAAc,QAAQ,eAC5E,UAAU,mBAEX;AAGF,QAAO;EACN,OAAO;EACP,SAAS,OAAO,gBAAgB,YAAY;EAC5C,gBAAgB,OAAO,gBAAgB,eAAe;EACtD,aAAa,OAAO,gBAAgB,YAAY;EAChD;CAED,eAAe,cAAc,SAAwB,MAAsC;EAC1F,MAAM,EACL,SACA,aACA,QAAQ,eACL,MAAM,OAAO,KAAK,UAAU;GAC/B;GACA;GACA;GACA,CAAC;AAEF,QAAM;AAIN,OAAK,MAAM,QAAQ,SAAS;AAC3B,OAAI,QAAQ,IAAI,KAAK,SAAS,CAC7B;AAGD,SAAM,KAAK,KAAK;AAChB,uBAAoB,OAAO,KAAK,QAAQ;;AAIzC,MAAI,mBAAmB,MAAM,YAC5B,QAAO,cAAc,WAAW;AAGjC,SAAO"}
|
|
1
|
+
{"version":3,"file":"CoinWithBalance.mjs","names":["bcs","balance"],"sources":["../../../src/transactions/intents/CoinWithBalance.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { InferInput } from 'valibot';\nimport {\n\tbigint,\n\tinteger,\n\tnumber,\n\tobject,\n\toptional,\n\tparse,\n\tpicklist,\n\tpipe,\n\tstring,\n\ttransform,\n\tunion,\n} from 'valibot';\n\nimport { ALLOWANCE_BALANCE, COIN_WITH_BALANCE } from './BalanceIntentNames.js';\nimport { resolveBalances } from './ResolveBalances.js';\n\nimport { bcs } from '../../bcs/index.js';\nimport { normalizeStructTag, normalizeSuiAddress } from '../../utils/sui-types.js';\nimport { TransactionCommands } from '../Commands.js';\nimport type { Argument } from '../data/internal.js';\nimport { Inputs } from '../Inputs.js';\nimport type { BuildTransactionOptions } from '../resolve.js';\nimport type { Transaction, TransactionResult } from '../Transaction.js';\nimport type { TransactionDataBuilder } from '../TransactionData.js';\nimport type { ClientWithCoreApi, SuiClientTypes } from '../../client/index.js';\n\nexport { COIN_WITH_BALANCE } from './BalanceIntentNames.js';\nconst SUI_TYPE = normalizeStructTag('0x2::sui::SUI');\n\nexport function coinWithBalance({\n\ttype = SUI_TYPE,\n\tbalance,\n\tuseGasCoin = true,\n}: {\n\tbalance: bigint | number;\n\ttype?: string;\n\tuseGasCoin?: boolean;\n}): (tx: Transaction) => TransactionResult {\n\tlet coinResult: TransactionResult | null = null;\n\n\treturn (tx: Transaction) => {\n\t\tif (coinResult) {\n\t\t\treturn coinResult;\n\t\t}\n\n\t\ttx.addIntentResolver(COIN_WITH_BALANCE, resolveBalances);\n\t\tconst coinType = type === 'gas' ? type : normalizeStructTag(type);\n\n\t\tcoinResult = tx.add(\n\t\t\tTransactionCommands.Intent({\n\t\t\t\tname: COIN_WITH_BALANCE,\n\t\t\t\tinputs: {},\n\t\t\t\tdata: {\n\t\t\t\t\ttype: coinType === SUI_TYPE && useGasCoin ? 'gas' : coinType,\n\t\t\t\t\tbalance: BigInt(balance),\n\t\t\t\t\toutputKind: 'coin',\n\t\t\t\t} satisfies InferInput<typeof CoinWithBalanceData>,\n\t\t\t}),\n\t\t);\n\n\t\treturn coinResult;\n\t};\n}\n\nexport function createBalance({\n\ttype = SUI_TYPE,\n\tbalance,\n\tuseGasCoin = true,\n}: {\n\tbalance: bigint | number;\n\ttype?: string;\n\tuseGasCoin?: boolean;\n}): (tx: Transaction) => TransactionResult {\n\tlet balanceResult: TransactionResult | null = null;\n\n\treturn (tx: Transaction) => {\n\t\tif (balanceResult) {\n\t\t\treturn balanceResult;\n\t\t}\n\n\t\ttx.addIntentResolver(COIN_WITH_BALANCE, resolveBalances);\n\t\tconst coinType = type === 'gas' ? type : normalizeStructTag(type);\n\n\t\tbalanceResult = tx.add(\n\t\t\tTransactionCommands.Intent({\n\t\t\t\tname: COIN_WITH_BALANCE,\n\t\t\t\tinputs: {},\n\t\t\t\tdata: {\n\t\t\t\t\ttype: coinType === SUI_TYPE && useGasCoin ? 'gas' : coinType,\n\t\t\t\t\tbalance: BigInt(balance),\n\t\t\t\t\toutputKind: 'balance',\n\t\t\t\t} satisfies InferInput<typeof CoinWithBalanceData>,\n\t\t\t}),\n\t\t);\n\n\t\treturn balanceResult;\n\t};\n}\n\n// `balance` is a bigint in memory, but serializing a transaction to JSON converts it to a\n// string. When that JSON is deserialized with `Transaction.from`, the value stays a string\n// (the intent `data` is opaque to the transaction schema), so coerce it back to a bigint here.\nconst CoinWithBalanceData = object({\n\ttype: string(),\n\tbalance: pipe(\n\t\tunion([bigint(), string(), pipe(number(), integer())]),\n\t\ttransform((value) => BigInt(value)),\n\t),\n\toutputKind: optional(picklist(['coin', 'balance'])),\n});\n\nexport async function resolveCoinBalance(\n\ttransactionData: TransactionDataBuilder,\n\tbuildOptions: BuildTransactionOptions,\n\tnext: () => Promise<void>,\n) {\n\ttype IntentInfo = { balance: bigint; outputKind: 'coin' | 'balance' };\n\n\tconst coinTypes = new Set<string>();\n\tconst totalByType = new Map<string, bigint>();\n\tconst intentsByType = new Map<string, IntentInfo[]>();\n\n\tif (!transactionData.sender) {\n\t\tthrow new Error('Sender must be set to resolve CoinWithBalance');\n\t}\n\n\tif (transactionData.commands.some((command) => command.$Intent?.name === ALLOWANCE_BALANCE)) {\n\t\tthrow new Error(\n\t\t\t'Resolve AllowanceBalance together with CoinWithBalance, or preserve both intents',\n\t\t);\n\t}\n\tconst reservedByType = new Map<string, bigint>();\n\tfor (const input of transactionData.inputs) {\n\t\tif (!input.FundsWithdrawal) continue;\n\t\tconst { withdrawFrom, typeArg, reservation } = input.FundsWithdrawal;\n\t\tconst owner =\n\t\t\twithdrawFrom.SenderAllowance?.funder ??\n\t\t\t(withdrawFrom.Sender\n\t\t\t\t? transactionData.sender\n\t\t\t\t: (transactionData.gasData.owner ?? transactionData.sender));\n\t\tif (normalizeSuiAddress(owner) !== normalizeSuiAddress(transactionData.sender)) continue;\n\t\tconst type = normalizeStructTag(typeArg.Balance);\n\t\treservedByType.set(type, (reservedByType.get(type) ?? 0n) + BigInt(reservation.MaxAmountU64));\n\t}\n\n\t// First pass: scan intents, collect per-type data, and resolve zero-balance intents in place.\n\tfor (const [i, command] of transactionData.commands.entries()) {\n\t\tif (command.$kind !== '$Intent' || command.$Intent.name !== COIN_WITH_BALANCE) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { type, balance, outputKind } = parse(CoinWithBalanceData, command.$Intent.data);\n\n\t\t// Zero-balance intents are resolved immediately — no coins or AB needed.\n\t\t// This is a 1:1 replacement so indices don't shift.\n\t\tif (balance === 0n) {\n\t\t\tconst coinType = type === 'gas' ? SUI_TYPE : type;\n\t\t\ttransactionData.replaceCommand(\n\t\t\t\ti,\n\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\ttarget: (outputKind ?? 'coin') === 'balance' ? '0x2::balance::zero' : '0x2::coin::zero',\n\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (type !== 'gas') {\n\t\t\tcoinTypes.add(type);\n\t\t}\n\n\t\ttotalByType.set(type, (totalByType.get(type) ?? 0n) + balance);\n\n\t\tif (!intentsByType.has(type)) intentsByType.set(type, []);\n\t\tintentsByType.get(type)!.push({ balance, outputKind: outputKind ?? 'coin' });\n\t}\n\n\tif (totalByType.has('gas') && totalByType.has(SUI_TYPE)) {\n\t\tthrow new Error(\n\t\t\t'Cannot mix SUI CoinWithBalance intents that use the gas coin with ones that do not (useGasCoin: false). Use one or the other.',\n\t\t);\n\t}\n\n\tconst usedIds = new Set<string>();\n\n\tfor (const input of transactionData.inputs) {\n\t\tif (input.Object?.ImmOrOwnedObject) {\n\t\t\tusedIds.add(input.Object.ImmOrOwnedObject.objectId);\n\t\t}\n\t\tif (input.UnresolvedObject?.objectId) {\n\t\t\tusedIds.add(input.UnresolvedObject.objectId);\n\t\t}\n\t}\n\n\tconst coinsByType = new Map<string, SuiClientTypes.Coin[]>();\n\tconst addressBalanceByType = new Map<string, bigint>();\n\tconst client = buildOptions.client;\n\tconst assumeSufficientAddressBalances = buildOptions.assumeSufficientAddressBalances;\n\n\tif (!client && !assumeSufficientAddressBalances) {\n\t\tthrow new Error(\n\t\t\t'Client must be provided to build or serialize transactions with CoinWithBalance intents',\n\t\t);\n\t}\n\n\tif (assumeSufficientAddressBalances) {\n\t\tfor (const [coinType, balance] of totalByType) {\n\t\t\taddressBalanceByType.set(coinType, balance);\n\t\t}\n\t} else {\n\t\tawait Promise.all([\n\t\t\t...[...coinTypes].map(async (coinType) => {\n\t\t\t\tconst { coins, addressBalance } = await getCoinsAndBalanceOfType({\n\t\t\t\t\tcoinType,\n\t\t\t\t\tbalance: totalByType.get(coinType)!,\n\t\t\t\t\tclient: client!,\n\t\t\t\t\towner: transactionData.sender!,\n\t\t\t\t\tusedIds,\n\t\t\t\t\treserved: reservedByType.get(coinType) ?? 0n,\n\t\t\t\t});\n\n\t\t\t\tcoinsByType.set(coinType, coins);\n\t\t\t\taddressBalanceByType.set(coinType, addressBalance);\n\t\t\t}),\n\t\t\ttotalByType.has('gas')\n\t\t\t\t? await client!.core\n\t\t\t\t\t\t.getBalance({\n\t\t\t\t\t\t\towner: transactionData.sender!,\n\t\t\t\t\t\t\tcoinType: SUI_TYPE,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.then(({ balance }) => {\n\t\t\t\t\t\t\taddressBalanceByType.set(\n\t\t\t\t\t\t\t\t'gas',\n\t\t\t\t\t\t\t\tavailableAddressBalance(balance.addressBalance, reservedByType.get(SUI_TYPE) ?? 0n),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})\n\t\t\t\t: null,\n\t\t]);\n\t}\n\n\tconst exactBalanceByType = new Map<string, boolean>();\n\tconst usedAddressBalance = new Set<string>();\n\n\t// Per-type state for Path 2 combined splits\n\ttype TypeState = { results: Argument[]; nextIntent: number };\n\tconst typeState = new Map<string, TypeState>();\n\n\tlet index = 0;\n\twhile (index < transactionData.commands.length) {\n\t\tconst transaction = transactionData.commands[index];\n\t\tif (transaction.$kind !== '$Intent' || transaction.$Intent.name !== COIN_WITH_BALANCE) {\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { type, balance } = parse(CoinWithBalanceData, transaction.$Intent.data);\n\t\tconst coinType = type === 'gas' ? SUI_TYPE : type;\n\t\tconst totalRequired = totalByType.get(type)!;\n\t\tconst addressBalance = addressBalanceByType.get(type) ?? 0n;\n\n\t\tconst commands = [];\n\t\tlet intentResult: Argument;\n\n\t\tconst intentsForType = intentsByType.get(type) ?? [];\n\t\tconst allBalance = intentsForType.every((i) => i.outputKind === 'balance');\n\n\t\tif (allBalance && addressBalance >= totalRequired) {\n\t\t\t// Path 1: All balance intents and AB sufficient — direct per-intent withdrawal.\n\t\t\t// No coins touched, enables parallel execution.\n\t\t\tcommands.push(\n\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\ttarget: '0x2::balance::redeem_funds',\n\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\targuments: [\n\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t'withdrawal',\n\t\t\t\t\t\t\tInputs.FundsWithdrawal({\n\t\t\t\t\t\t\t\treservation: {\n\t\t\t\t\t\t\t\t\t$kind: 'MaxAmountU64',\n\t\t\t\t\t\t\t\t\tMaxAmountU64: String(balance),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttypeArg: { $kind: 'Balance', Balance: coinType },\n\t\t\t\t\t\t\t\twithdrawFrom: { $kind: 'Sender', Sender: true },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tintentResult = {\n\t\t\t\t$kind: 'NestedResult',\n\t\t\t\tNestedResult: [index + commands.length - 1, 0],\n\t\t\t};\n\t\t} else {\n\t\t\t// Path 2: Merge and Split — build a merged coin, split all intents at once.\n\n\t\t\tif (!typeState.has(type)) {\n\t\t\t\tconst intents = intentsForType;\n\n\t\t\t\t// Step 1: Build sources and merge\n\t\t\t\tconst sources: Argument[] = [];\n\n\t\t\t\tif (addressBalance >= totalRequired) {\n\t\t\t\t\t// AB sufficient — source entirely from address balance, no coins needed.\n\t\t\t\t\tusedAddressBalance.add(type);\n\n\t\t\t\t\tcommands.push(\n\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\ttarget: '0x2::coin::redeem_funds',\n\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t\t'withdrawal',\n\t\t\t\t\t\t\t\t\tInputs.FundsWithdrawal({\n\t\t\t\t\t\t\t\t\t\treservation: {\n\t\t\t\t\t\t\t\t\t\t\t$kind: 'MaxAmountU64',\n\t\t\t\t\t\t\t\t\t\t\tMaxAmountU64: String(totalRequired),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\ttypeArg: { $kind: 'Balance', Balance: coinType },\n\t\t\t\t\t\t\t\t\t\twithdrawFrom: { $kind: 'Sender', Sender: true },\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tsources.push({ $kind: 'Result', Result: index + commands.length - 1 });\n\t\t\t\t} else if (type === 'gas') {\n\t\t\t\t\tsources.push({ $kind: 'GasCoin', GasCoin: true });\n\t\t\t\t} else {\n\t\t\t\t\tconst coins = coinsByType.get(type)!;\n\t\t\t\t\tconst loadedCoinBalance = coins.reduce((sum, c) => sum + BigInt(c.balance), 0n);\n\t\t\t\t\tconst abNeeded =\n\t\t\t\t\t\ttotalRequired > loadedCoinBalance ? totalRequired - loadedCoinBalance : 0n;\n\n\t\t\t\t\texactBalanceByType.set(type, loadedCoinBalance + abNeeded === totalRequired);\n\n\t\t\t\t\tfor (const coin of coins) {\n\t\t\t\t\t\tsources.push(\n\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t'object',\n\t\t\t\t\t\t\t\tInputs.ObjectRef({\n\t\t\t\t\t\t\t\t\tobjectId: coin.objectId,\n\t\t\t\t\t\t\t\t\tdigest: coin.digest,\n\t\t\t\t\t\t\t\t\tversion: coin.version,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (abNeeded > 0n) {\n\t\t\t\t\t\tusedAddressBalance.add(type);\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::redeem_funds',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t\t\t'withdrawal',\n\t\t\t\t\t\t\t\t\t\tInputs.FundsWithdrawal({\n\t\t\t\t\t\t\t\t\t\t\treservation: {\n\t\t\t\t\t\t\t\t\t\t\t\t$kind: 'MaxAmountU64',\n\t\t\t\t\t\t\t\t\t\t\t\tMaxAmountU64: String(abNeeded),\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttypeArg: { $kind: 'Balance', Balance: coinType },\n\t\t\t\t\t\t\t\t\t\t\twithdrawFrom: { $kind: 'Sender', Sender: true },\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsources.push({ $kind: 'Result', Result: index + commands.length - 1 });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst baseCoin = sources[0];\n\t\t\t\tconst rest = sources.slice(1);\n\t\t\t\tfor (let i = 0; i < rest.length; i += 500) {\n\t\t\t\t\tcommands.push(TransactionCommands.MergeCoins(baseCoin, rest.slice(i, i + 500)));\n\t\t\t\t}\n\n\t\t\t\t// Step 2: Combined SplitCoins for all intents of this type\n\t\t\t\tconst splitCmdIndex = index + commands.length;\n\t\t\t\tcommands.push(\n\t\t\t\t\tTransactionCommands.SplitCoins(\n\t\t\t\t\t\tbaseCoin,\n\t\t\t\t\t\tintents.map((i) =>\n\t\t\t\t\t\t\ttransactionData.addInput('pure', Inputs.Pure(bcs.u64().serialize(i.balance))),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\t// Build per-intent results, adding into_balance conversions for balance intents\n\t\t\t\tconst results: Argument[] = [];\n\t\t\t\tfor (let i = 0; i < intents.length; i++) {\n\t\t\t\t\tconst splitResult: Argument = {\n\t\t\t\t\t\t$kind: 'NestedResult',\n\t\t\t\t\t\tNestedResult: [splitCmdIndex, i],\n\t\t\t\t\t};\n\n\t\t\t\t\tif (intents[i].outputKind === 'balance') {\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::into_balance',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [splitResult],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tresults.push({\n\t\t\t\t\t\t\t$kind: 'NestedResult',\n\t\t\t\t\t\t\tNestedResult: [index + commands.length - 1, 0],\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresults.push(splitResult);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Step 3: Remainder handling\n\t\t\t\t//\n\t\t\t\t// Add cleanup to this replacement command list rather than appending\n\t\t\t\t// it to the complete transaction. Appending cleanup can place it after\n\t\t\t\t// a MoveCall that consumes Random, which Sui rejects.\n\t\t\t\t//\n\t\t\t\t// When gas type used GasCoin (not AB), leftover stays in the gas coin\n\t\t\t\t// -- no remainder handling is needed.\n\t\t\t\tif (type !== 'gas' || usedAddressBalance.has(type)) {\n\t\t\t\t\tconst hasBalanceIntent = intents.some((intent) => intent.outputKind === 'balance');\n\t\t\t\t\tconst sourcedFromAB = usedAddressBalance.has(type);\n\n\t\t\t\t\tif (hasBalanceIntent || sourcedFromAB) {\n\t\t\t\t\t\t// Sourced from AB or balance intents exist: send remainder back to sender's address\n\t\t\t\t\t\t// balance. `coin::send_funds` is gasless-eligible and handles zero amounts.\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::send_funds',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [\n\t\t\t\t\t\t\t\t\tbaseCoin,\n\t\t\t\t\t\t\t\t\ttransactionData.addInput(\n\t\t\t\t\t\t\t\t\t\t'pure',\n\t\t\t\t\t\t\t\t\t\tInputs.Pure(bcs.Address.serialize(transactionData.sender!)),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (exactBalanceByType.get(type)) {\n\t\t\t\t\t\t// Coin-only with exact match: destroy the zero-value dust coin.\n\t\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t\tTransactionCommands.MoveCall({\n\t\t\t\t\t\t\t\ttarget: '0x2::coin::destroy_zero',\n\t\t\t\t\t\t\t\ttypeArguments: [coinType],\n\t\t\t\t\t\t\t\targuments: [baseCoin],\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// Coin-only with surplus: merged coin stays with sender as an owned object.\n\t\t\t\t}\n\n\t\t\t\ttypeState.set(type, { results, nextIntent: 0 });\n\t\t\t}\n\n\t\t\tconst state = typeState.get(type)!;\n\t\t\tintentResult = state.results[state.nextIntent++];\n\t\t}\n\n\t\ttransactionData.replaceCommand(\n\t\t\tindex,\n\t\t\tcommands,\n\t\t\tintentResult as { NestedResult: [number, number] },\n\t\t);\n\n\t\t// Advance past the replacement. When commands is empty (subsequent intents\n\t\t// of a combined split), the command was removed and the next command shifted\n\t\t// into this position — so we stay at the same index.\n\t\tindex += commands.length;\n\t}\n\n\treturn next();\n}\n\nasync function getCoinsAndBalanceOfType({\n\tcoinType,\n\tbalance,\n\tclient,\n\towner,\n\tusedIds,\n\treserved,\n}: {\n\tcoinType: string;\n\tbalance: bigint;\n\tclient: ClientWithCoreApi;\n\towner: string;\n\tusedIds: Set<string>;\n\treserved: bigint;\n}): Promise<{\n\tcoins: SuiClientTypes.Coin[];\n\tbalance: bigint;\n\taddressBalance: bigint;\n\tcoinBalance: bigint;\n}> {\n\tlet remainingBalance = balance;\n\tconst coins: SuiClientTypes.Coin[] = [];\n\tconst balanceRequest = client.core.getBalance({ owner, coinType }).then(({ balance }) => {\n\t\tconst addressBalance = availableAddressBalance(balance.addressBalance, reserved);\n\t\tremainingBalance -= addressBalance;\n\n\t\treturn {\n\t\t\t...balance,\n\t\t\taddressBalance: String(addressBalance),\n\t\t\tbalance: String(BigInt(balance.balance) - reserved),\n\t\t};\n\t});\n\n\tconst [allCoins, balanceResponse] = await Promise.all([loadMoreCoins(), balanceRequest]);\n\n\tif (BigInt(balanceResponse.balance) < balance) {\n\t\tthrow new Error(\n\t\t\t`Insufficient balance of ${coinType} for owner ${owner}. Required: ${balance}, Available: ${\n\t\t\t\tbalance - remainingBalance\n\t\t\t}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tcoins: allCoins,\n\t\tbalance: BigInt(balanceResponse.coinBalance),\n\t\taddressBalance: BigInt(balanceResponse.addressBalance),\n\t\tcoinBalance: BigInt(balanceResponse.coinBalance),\n\t};\n\n\tasync function loadMoreCoins(cursor: string | null = null): Promise<SuiClientTypes.Coin[]> {\n\t\tconst {\n\t\t\tobjects,\n\t\t\thasNextPage,\n\t\t\tcursor: nextCursor,\n\t\t} = await client.core.listCoins({\n\t\t\towner,\n\t\t\tcoinType,\n\t\t\tcursor,\n\t\t});\n\n\t\tawait balanceRequest;\n\n\t\t// Always load all coins from the page (except already-used ones).\n\t\t// This merges all available coins rather than leaving dust.\n\t\tfor (const coin of objects) {\n\t\t\tif (usedIds.has(coin.objectId)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcoins.push(coin);\n\t\t\tremainingBalance -= BigInt(coin.balance);\n\t\t}\n\n\t\t// Only paginate if loaded coins + AB are still insufficient\n\t\tif (remainingBalance > 0n && hasNextPage) {\n\t\t\treturn loadMoreCoins(nextCursor);\n\t\t}\n\n\t\treturn coins;\n\t}\n}\n\nfunction availableAddressBalance(balance: string, reserved: bigint): bigint {\n\tconst available = BigInt(balance) - reserved;\n\tif (available < 0n) {\n\t\tthrow new Error(\n\t\t\t`Insufficient address balance for existing withdrawals. Required: ${reserved}, Available: ${balance}`,\n\t\t);\n\t}\n\treturn available;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ALLOWANCE_BALANCE, COIN_WITH_BALANCE } from "./BalanceIntentNames.mjs";
|
|
2
|
+
import { resolveCoinBalance } from "./CoinWithBalance.mjs";
|
|
3
|
+
import { resolveAllowanceBalance } from "./AllowanceBalance.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/transactions/intents/ResolveBalances.ts
|
|
6
|
+
async function resolveBalances(transactionData, options, next) {
|
|
7
|
+
const intents = new Set(options.intentNames ?? [ALLOWANCE_BALANCE, COIN_WITH_BALANCE]);
|
|
8
|
+
const shouldResolve = (name) => intents.has(name) && !options.supportedIntents?.includes(name) && transactionData.commands.some((command) => command.$Intent?.name === name);
|
|
9
|
+
if (shouldResolve(ALLOWANCE_BALANCE)) await resolveAllowanceBalance(transactionData, options, async () => {});
|
|
10
|
+
if (shouldResolve(COIN_WITH_BALANCE)) await resolveCoinBalance(transactionData, options, async () => {});
|
|
11
|
+
await next();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { resolveBalances };
|
|
16
|
+
//# sourceMappingURL=ResolveBalances.mjs.map
|