@mysten/sui 2.29.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/bcs/bcs.d.mts +6 -6
  3. package/dist/bcs/bcs.d.mts.map +1 -1
  4. package/dist/bcs/bcs.mjs +5 -1
  5. package/dist/bcs/bcs.mjs.map +1 -1
  6. package/dist/bcs/index.d.mts +139 -47
  7. package/dist/bcs/index.d.mts.map +1 -1
  8. package/dist/bcs/types.d.mts.map +1 -1
  9. package/dist/client/core-resolver.d.mts.map +1 -1
  10. package/dist/client/core-resolver.mjs +4 -6
  11. package/dist/client/core-resolver.mjs.map +1 -1
  12. package/dist/client/transaction-resolver.mjs +35 -8
  13. package/dist/client/transaction-resolver.mjs.map +1 -1
  14. package/dist/cryptography/signature.d.mts +8 -8
  15. package/dist/graphql/generated/tada-env.d.mts +74 -0
  16. package/dist/grpc/proto/sui/rpc/v2/input.d.mts +21 -1
  17. package/dist/grpc/proto/sui/rpc/v2/input.d.mts.map +1 -1
  18. package/dist/grpc/proto/sui/rpc/v2/input.mjs +21 -0
  19. package/dist/grpc/proto/sui/rpc/v2/input.mjs.map +1 -1
  20. package/dist/grpc/proto/sui/rpc/v2/ledger_service.client.d.mts +4 -4
  21. package/dist/grpc/proto/sui/rpc/v2/move_package_service.client.d.mts +4 -4
  22. package/dist/grpc/proto/sui/rpc/v2/signature_verification_service.client.d.mts +4 -4
  23. package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
  24. package/dist/grpc/proto/sui/rpc/v2/subscription_service.client.d.mts +4 -4
  25. package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.client.d.mts +4 -4
  26. package/dist/jsonRpc/core.mjs +1 -1
  27. package/dist/jsonRpc/core.mjs.map +1 -1
  28. package/dist/transactions/Transaction.d.mts +48 -46
  29. package/dist/transactions/Transaction.d.mts.map +1 -1
  30. package/dist/transactions/Transaction.mjs +65 -24
  31. package/dist/transactions/Transaction.mjs.map +1 -1
  32. package/dist/transactions/data/internal.d.mts +12 -0
  33. package/dist/transactions/data/internal.d.mts.map +1 -1
  34. package/dist/transactions/data/internal.mjs +5 -1
  35. package/dist/transactions/data/internal.mjs.map +1 -1
  36. package/dist/transactions/data/v2.d.mts +5 -0
  37. package/dist/transactions/data/v2.d.mts.map +1 -1
  38. package/dist/transactions/index.d.mts +3 -2
  39. package/dist/transactions/intents/AllowanceBalance.mjs +147 -0
  40. package/dist/transactions/intents/AllowanceBalance.mjs.map +1 -0
  41. package/dist/transactions/intents/BalanceIntentNames.mjs +7 -0
  42. package/dist/transactions/intents/BalanceIntentNames.mjs.map +1 -0
  43. package/dist/transactions/intents/BalanceOptions.d.mts +27 -0
  44. package/dist/transactions/intents/BalanceOptions.d.mts.map +1 -0
  45. package/dist/transactions/intents/BalanceOptions.mjs +12 -0
  46. package/dist/transactions/intents/BalanceOptions.mjs.map +1 -0
  47. package/dist/transactions/intents/CoinWithBalance.d.mts.map +1 -1
  48. package/dist/transactions/intents/CoinWithBalance.mjs +35 -12
  49. package/dist/transactions/intents/CoinWithBalance.mjs.map +1 -1
  50. package/dist/transactions/intents/ResolveBalances.mjs +16 -0
  51. package/dist/transactions/intents/ResolveBalances.mjs.map +1 -0
  52. package/dist/transactions/resolution-utils.mjs +13 -0
  53. package/dist/transactions/resolution-utils.mjs.map +1 -0
  54. package/dist/transactions/resolve.d.mts +8 -0
  55. package/dist/transactions/resolve.d.mts.map +1 -1
  56. package/dist/transactions/resolve.mjs +7 -3
  57. package/dist/transactions/resolve.mjs.map +1 -1
  58. package/dist/version.mjs +1 -1
  59. package/dist/version.mjs.map +1 -1
  60. package/dist/zklogin/bcs.d.mts +14 -14
  61. package/docs/llms-index.md +1 -0
  62. package/docs/migrations/sui-2.0/json-rpc-migration.md +50 -1
  63. package/docs/transactions/allowances.md +176 -0
  64. package/docs/transactions/basics.md +19 -14
  65. package/docs/transactions/coins-and-balances.md +12 -9
  66. package/docs/transactions/offline.md +137 -88
  67. package/package.json +2 -2
  68. package/src/bcs/bcs.ts +4 -0
  69. package/src/bcs/types.ts +2 -1
  70. package/src/client/core-resolver.ts +8 -11
  71. package/src/client/transaction-resolver.ts +43 -9
  72. package/src/graphql/generated/schema.graphql +87 -42
  73. package/src/graphql/generated/tada-env.ts +84 -0
  74. package/src/grpc/proto/sui/rpc/v2/input.ts +22 -0
  75. package/src/jsonRpc/core.ts +3 -4
  76. package/src/transactions/Transaction.ts +71 -53
  77. package/src/transactions/data/internal.ts +4 -0
  78. package/src/transactions/index.ts +3 -0
  79. package/src/transactions/intents/AllowanceBalance.ts +204 -0
  80. package/src/transactions/intents/BalanceIntentNames.ts +5 -0
  81. package/src/transactions/intents/BalanceOptions.ts +45 -0
  82. package/src/transactions/intents/CoinWithBalance.ts +82 -32
  83. package/src/transactions/intents/ResolveBalances.ts +30 -0
  84. package/src/transactions/resolution-utils.ts +18 -0
  85. package/src/transactions/resolve.ts +35 -2
  86. 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":"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"}
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":"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"}
@@ -82,6 +82,11 @@ declare const SerializedTransactionDataV2Schema: valibot0.ObjectSchema<{
82
82
  Sender: true;
83
83
  } | {
84
84
  Sponsor: true;
85
+ } | {
86
+ SenderAllowance: {
87
+ funder: string;
88
+ allowance: string;
89
+ };
85
90
  };
86
91
  };
87
92
  }>>, undefined>;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEU,2BAAA,GAA8B,WAAA,QAAmB,iCAAA"}
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 { Transaction, TransactionCopyOptions, TransactionObjectArgument, TransactionObjectInput, TransactionResult, isTransaction } from "./Transaction.mjs";
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":"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"}
@@ -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":";;;;;iBA+BgB,eAAA,CAAA;EACf,IAAA;EACA,OAAA;EACA;AAAA;EAEA,OAAA;EACA,IAAA;EACA,UAAA;AAAA,KACI,EAAA,EAAI,WAAA,KAAgB,iBAAA"}
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, resolveCoinBalance);
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, resolveCoinBalance);
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);
@@ -85,14 +95,17 @@ async function resolveCoinBalance(transactionData, buildOptions, next) {
85
95
  const coinsByType = /* @__PURE__ */ new Map();
86
96
  const addressBalanceByType = /* @__PURE__ */ new Map();
87
97
  const client = buildOptions.client;
88
- if (!client) throw new Error("Client must be provided to build or serialize transactions with CoinWithBalance intents");
89
- await Promise.all([...[...coinTypes].map(async (coinType) => {
98
+ const assumeSufficientAddressBalances = buildOptions.assumeSufficientAddressBalances;
99
+ if (!client && !assumeSufficientAddressBalances) throw new Error("Client must be provided to build or serialize transactions with CoinWithBalance intents");
100
+ if (assumeSufficientAddressBalances) for (const [coinType, balance] of totalByType) addressBalanceByType.set(coinType, balance);
101
+ else await Promise.all([...[...coinTypes].map(async (coinType) => {
90
102
  const { coins, addressBalance } = await getCoinsAndBalanceOfType({
91
103
  coinType,
92
104
  balance: totalByType.get(coinType),
93
105
  client,
94
106
  owner: transactionData.sender,
95
- usedIds
107
+ usedIds,
108
+ reserved: reservedByType.get(coinType) ?? 0n
96
109
  });
97
110
  coinsByType.set(coinType, coins);
98
111
  addressBalanceByType.set(coinType, addressBalance);
@@ -100,7 +113,7 @@ async function resolveCoinBalance(transactionData, buildOptions, next) {
100
113
  owner: transactionData.sender,
101
114
  coinType: SUI_TYPE
102
115
  }).then(({ balance }) => {
103
- addressBalanceByType.set("gas", BigInt(balance.addressBalance));
116
+ addressBalanceByType.set("gas", availableAddressBalance(balance.addressBalance, reservedByType.get(SUI_TYPE) ?? 0n));
104
117
  }) : null]);
105
118
  const exactBalanceByType = /* @__PURE__ */ new Map();
106
119
  const usedAddressBalance = /* @__PURE__ */ new Set();
@@ -260,15 +273,20 @@ async function resolveCoinBalance(transactionData, buildOptions, next) {
260
273
  }
261
274
  return next();
262
275
  }
263
- async function getCoinsAndBalanceOfType({ coinType, balance, client, owner, usedIds }) {
276
+ async function getCoinsAndBalanceOfType({ coinType, balance, client, owner, usedIds, reserved }) {
264
277
  let remainingBalance = balance;
265
278
  const coins = [];
266
279
  const balanceRequest = client.core.getBalance({
267
280
  owner,
268
281
  coinType
269
282
  }).then(({ balance: balance$1 }) => {
270
- remainingBalance -= BigInt(balance$1.addressBalance);
271
- return balance$1;
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
+ };
272
290
  });
273
291
  const [allCoins, balanceResponse] = await Promise.all([loadMoreCoins(), balanceRequest]);
274
292
  if (BigInt(balanceResponse.balance) < balance) throw new Error(`Insufficient balance of ${coinType} for owner ${owner}. Required: ${balance}, Available: ${balance - remainingBalance}`);
@@ -294,7 +312,12 @@ async function getCoinsAndBalanceOfType({ coinType, balance, client, owner, used
294
312
  return coins;
295
313
  }
296
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
+ }
297
320
 
298
321
  //#endregion
299
- export { COIN_WITH_BALANCE, coinWithBalance, createBalance, resolveCoinBalance };
322
+ export { coinWithBalance, createBalance, resolveCoinBalance };
300
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\n\tif (!client) {\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\tawait Promise.all([\n\t\t...[...coinTypes].map(async (coinType) => {\n\t\t\tconst { coins, addressBalance } = await getCoinsAndBalanceOfType({\n\t\t\t\tcoinType,\n\t\t\t\tbalance: totalByType.get(coinType)!,\n\t\t\t\tclient,\n\t\t\t\towner: transactionData.sender!,\n\t\t\t\tusedIds,\n\t\t\t});\n\n\t\t\tcoinsByType.set(coinType, coins);\n\t\t\taddressBalanceByType.set(coinType, addressBalance);\n\t\t}),\n\t\ttotalByType.has('gas')\n\t\t\t? await client.core\n\t\t\t\t\t.getBalance({\n\t\t\t\t\t\towner: transactionData.sender!,\n\t\t\t\t\t\tcoinType: SUI_TYPE,\n\t\t\t\t\t})\n\t\t\t\t\t.then(({ balance }) => {\n\t\t\t\t\t\taddressBalanceByType.set('gas', BigInt(balance.addressBalance));\n\t\t\t\t\t})\n\t\t\t: null,\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":"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"}
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":";;;;;;;;;AAgCA,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,gBAAgB;EACxD,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,gBAAgB;EACxD,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;AAGjE,KAAI,gBAAgB,SAAS,MAAM,YAAY,QAAQ,SAAS,SAAS,kBAAkB,CAC1F,OAAM,IAAI,MACT,mFACA;CAEF,MAAM,iCAAiB,IAAI,KAAqB;AAChD,MAAK,MAAM,SAAS,gBAAgB,QAAQ;AAC3C,MAAI,CAAC,MAAM,gBAAiB;EAC5B,MAAM,EAAE,cAAc,SAAS,gBAAgB,MAAM;AAMrD,MAAI,oBAJH,aAAa,iBAAiB,WAC7B,aAAa,SACX,gBAAgB,SACf,gBAAgB,QAAQ,SAAS,gBAAgB,QACxB,KAAK,oBAAoB,gBAAgB,OAAO,CAAE;EAChF,MAAM,OAAO,mBAAmB,QAAQ,QAAQ;AAChD,iBAAe,IAAI,OAAO,eAAe,IAAI,KAAK,IAAI,MAAM,OAAO,YAAY,aAAa,CAAC;;AAI9F,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,UAAU,eAAe,IAAI,SAAS,IAAI;GAC1C,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,IACpB,OACA,wBAAwB,QAAQ,gBAAgB,eAAe,IAAI,SAAS,IAAI,GAAG,CACnF;GACA,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,SACA,YAaE;CACF,IAAI,mBAAmB;CACvB,MAAM,QAA+B,EAAE;CACvC,MAAM,iBAAiB,OAAO,KAAK,WAAW;EAAE;EAAO;EAAU,CAAC,CAAC,MAAM,EAAE,yBAAc;EACxF,MAAM,iBAAiB,wBAAwBC,UAAQ,gBAAgB,SAAS;AAChF,sBAAoB;AAEpB,SAAO;GACN,GAAGA;GACH,gBAAgB,OAAO,eAAe;GACtC,SAAS,OAAO,OAAOA,UAAQ,QAAQ,GAAG,SAAS;GACnD;GACA;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;;;AAIT,SAAS,wBAAwB,SAAiB,UAA0B;CAC3E,MAAM,YAAY,OAAO,QAAQ,GAAG;AACpC,KAAI,YAAY,GACf,OAAM,IAAI,MACT,oEAAoE,SAAS,eAAe,UAC5F;AAEF,QAAO"}