@mysten/sui 2.30.0 → 2.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/dist/bcs/bcs.d.mts +6 -6
- package/dist/bcs/bcs.d.mts.map +1 -1
- package/dist/bcs/bcs.mjs +5 -1
- package/dist/bcs/bcs.mjs.map +1 -1
- package/dist/bcs/index.d.mts +139 -47
- package/dist/bcs/index.d.mts.map +1 -1
- package/dist/bcs/types.d.mts.map +1 -1
- package/dist/client/core-resolver.d.mts.map +1 -1
- package/dist/client/core-resolver.mjs +5 -3
- package/dist/client/core-resolver.mjs.map +1 -1
- package/dist/client/transaction-resolver.mjs +35 -8
- package/dist/client/transaction-resolver.mjs.map +1 -1
- package/dist/graphql/generated/tada-env.d.mts +74 -0
- package/dist/grpc/proto/sui/forking/v1alpha/forking_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/input.d.mts +21 -1
- package/dist/grpc/proto/sui/rpc/v2/input.d.mts.map +1 -1
- package/dist/grpc/proto/sui/rpc/v2/input.mjs +21 -0
- package/dist/grpc/proto/sui/rpc/v2/input.mjs.map +1 -1
- package/dist/grpc/proto/sui/rpc/v2/name_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/state_service.client.d.mts +4 -4
- package/dist/grpc/proto/sui/rpc/v2/transaction_execution_service.client.d.mts +4 -4
- package/dist/jsonRpc/core.mjs +1 -1
- package/dist/jsonRpc/core.mjs.map +1 -1
- package/dist/transactions/Transaction.d.mts +47 -42
- package/dist/transactions/Transaction.d.mts.map +1 -1
- package/dist/transactions/Transaction.mjs +65 -24
- package/dist/transactions/Transaction.mjs.map +1 -1
- package/dist/transactions/data/internal.d.mts +12 -0
- package/dist/transactions/data/internal.d.mts.map +1 -1
- package/dist/transactions/data/internal.mjs +5 -1
- package/dist/transactions/data/internal.mjs.map +1 -1
- package/dist/transactions/data/v2.d.mts +5 -0
- package/dist/transactions/data/v2.d.mts.map +1 -1
- package/dist/transactions/index.d.mts +3 -2
- package/dist/transactions/intents/AllowanceBalance.mjs +147 -0
- package/dist/transactions/intents/AllowanceBalance.mjs.map +1 -0
- package/dist/transactions/intents/BalanceIntentNames.mjs +7 -0
- package/dist/transactions/intents/BalanceIntentNames.mjs.map +1 -0
- package/dist/transactions/intents/BalanceOptions.d.mts +27 -0
- package/dist/transactions/intents/BalanceOptions.d.mts.map +1 -0
- package/dist/transactions/intents/BalanceOptions.mjs +12 -0
- package/dist/transactions/intents/BalanceOptions.mjs.map +1 -0
- package/dist/transactions/intents/CoinWithBalance.d.mts.map +1 -1
- package/dist/transactions/intents/CoinWithBalance.mjs +31 -10
- package/dist/transactions/intents/CoinWithBalance.mjs.map +1 -1
- package/dist/transactions/intents/ResolveBalances.mjs +16 -0
- package/dist/transactions/intents/ResolveBalances.mjs.map +1 -0
- package/dist/transactions/resolve.d.mts.map +1 -1
- package/dist/transactions/resolve.mjs +1 -1
- package/dist/transactions/resolve.mjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/version.mjs.map +1 -1
- package/dist/zklogin/bcs.d.mts +14 -14
- package/docs/llms-index.md +1 -0
- package/docs/transactions/allowances.md +176 -0
- package/docs/transactions/coins-and-balances.md +12 -9
- package/package.json +1 -1
- package/src/bcs/bcs.ts +4 -0
- package/src/bcs/types.ts +2 -1
- package/src/client/core-resolver.ts +12 -6
- package/src/client/transaction-resolver.ts +43 -9
- package/src/graphql/generated/schema.graphql +87 -42
- package/src/graphql/generated/tada-env.ts +84 -0
- package/src/grpc/proto/sui/rpc/v2/input.ts +22 -0
- package/src/jsonRpc/core.ts +3 -4
- package/src/transactions/Transaction.ts +70 -49
- package/src/transactions/data/internal.ts +4 -0
- package/src/transactions/index.ts +3 -0
- package/src/transactions/intents/AllowanceBalance.ts +204 -0
- package/src/transactions/intents/BalanceIntentNames.ts +5 -0
- package/src/transactions/intents/BalanceOptions.ts +45 -0
- package/src/transactions/intents/CoinWithBalance.ts +51 -8
- package/src/transactions/intents/ResolveBalances.ts +30 -0
- package/src/transactions/resolve.ts +6 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Allowances
|
|
2
|
+
|
|
3
|
+
> Create allowances and spend from another account's address balance
|
|
4
|
+
|
|
5
|
+
An [allowance](https://docs.sui.io/references/framework/sui_sui/allowance) lets a **spender** use a
|
|
6
|
+
**funder's** address balance, subject to spending limits. The spender signs transactions that use
|
|
7
|
+
it. The network must have allowance support enabled (protocol v137 or later).
|
|
8
|
+
|
|
9
|
+
## Creating an allowance
|
|
10
|
+
|
|
11
|
+
This non-app allowance permits up to 100 USDC of spending over 24 hours. `funder` is the signer
|
|
12
|
+
creating the allowance. Replace `0xUsdcPackage::usdc::USDC` with your network's USDC type; amounts
|
|
13
|
+
use its six decimal places.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
|
|
17
|
+
const USDC = '0xUsdcPackage::usdc::USDC';
|
|
18
|
+
const balanceType = `0x2::balance::Balance<${USDC}>`;
|
|
19
|
+
const expirationMs = BigInt(Date.now() + 24 * 60 * 60 * 1000);
|
|
20
|
+
const tx = new Transaction();
|
|
21
|
+
|
|
22
|
+
// RateLimit is a Move type, so construct its empty option with a Move call.
|
|
23
|
+
const noRateLimit = tx.moveCall({
|
|
24
|
+
target: '0x1::option::none',
|
|
25
|
+
typeArguments: ['0x2::allowance::RateLimit'],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
tx.moveCall({
|
|
29
|
+
target: '0x2::allowance::new',
|
|
30
|
+
typeArguments: [balanceType],
|
|
31
|
+
arguments: [
|
|
32
|
+
tx.pure.string('USDC spending allowance'),
|
|
33
|
+
tx.pure.address(spenderAddress),
|
|
34
|
+
tx.pure.option('u256', 100_000_000n), // Lifetime cap: 100 USDC
|
|
35
|
+
tx.pure.option('u64', null), // No delayed start
|
|
36
|
+
tx.pure.option('u64', expirationMs),
|
|
37
|
+
noRateLimit,
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const result = await client.core.signAndExecuteTransaction({
|
|
42
|
+
transaction: tx,
|
|
43
|
+
signer: funder,
|
|
44
|
+
include: { effects: true },
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (result.$kind === 'FailedTransaction') {
|
|
48
|
+
throw new Error(result.FailedTransaction.status.error?.message ?? 'Allowance creation failed');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// This transaction creates one shared object: the allowance.
|
|
52
|
+
const allowance = result.Transaction.effects!.changedObjects.find(
|
|
53
|
+
(change) => change.idOperation === 'Created' && change.outputOwner?.$kind === 'Shared',
|
|
54
|
+
);
|
|
55
|
+
if (!allowance) throw new Error('No allowance was created');
|
|
56
|
+
|
|
57
|
+
const allowanceId = allowance.objectId;
|
|
58
|
+
await client.core.waitForTransaction({ digest: result.Transaction.digest });
|
|
59
|
+
// Give allowanceId to the spender.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`allowance::new` takes `Balance<USDC>` as its type argument; the spending helpers take `USDC`.
|
|
63
|
+
Creation also sends the funder an `AllowanceCap`, which can revoke the allowance.
|
|
64
|
+
|
|
65
|
+
Creating an allowance does not reserve or deposit funds. The funder must have enough USDC in its
|
|
66
|
+
[address balance](https://docs.sui.io/onchain-finance/asset-custody/address-balances/using-address-balances#sending-funds)
|
|
67
|
+
when the spender withdraws.
|
|
68
|
+
|
|
69
|
+
### Limits and expiration
|
|
70
|
+
|
|
71
|
+
An allowance requires both a lifetime cap and an expiration, unless it has a recurring rate limit.
|
|
72
|
+
Lifetime caps must be positive `u256` amounts. Start and expiration times use Unix milliseconds; if
|
|
73
|
+
both are set, the start must be earlier. Names can be at most 128 bytes.
|
|
74
|
+
|
|
75
|
+
For recurring spending, use `allowance::periodic_rate_limit(period_ms, limit)` or
|
|
76
|
+
`allowance::monthly_rate_limit(limit)`. Wrap the result in `0x1::option::some<RateLimit>` and pass
|
|
77
|
+
it as the last argument to `allowance::new`. A rate limit can replace the lifetime cap and
|
|
78
|
+
expiration, or apply alongside them.
|
|
79
|
+
|
|
80
|
+
## Spending from an allowance
|
|
81
|
+
|
|
82
|
+
Pass the shared allowance ID and sign with the spender's key:
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
|
|
86
|
+
const USDC = '0xUsdcPackage::usdc::USDC';
|
|
87
|
+
const tx = new Transaction();
|
|
88
|
+
const balance = tx.balance({
|
|
89
|
+
allowance: '0xAllowanceId',
|
|
90
|
+
balance: 10_000_000n, // 10 USDC
|
|
91
|
+
type: USDC,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
tx.moveCall({
|
|
95
|
+
target: '0xPackage::pool::deposit',
|
|
96
|
+
typeArguments: [USDC],
|
|
97
|
+
arguments: [tx.object('0xPoolId'), balance],
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await client.core.signAndExecuteTransaction({ transaction: tx, signer: spender });
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Use `tx.coin()` instead when the next operation expects a `Coin<T>`. Both helpers default to SUI, so
|
|
104
|
+
pass `type: USDC` explicitly. Each amount must fit in a `u64`.
|
|
105
|
+
|
|
106
|
+
The SDK looks up the funder from the allowance ID. Spending draws only from that funder's address
|
|
107
|
+
balance and must satisfy the allowance's limits and expiration. The sender or a sponsor must pay gas
|
|
108
|
+
separately; do not combine `allowance` with `useGasCoin`.
|
|
109
|
+
|
|
110
|
+
### Using a known funder
|
|
111
|
+
|
|
112
|
+
Pass the funder alongside the ID to skip the allowance lookup:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
|
|
116
|
+
const USDC = '0xUsdcPackage::usdc::USDC';
|
|
117
|
+
const tx = new Transaction();
|
|
118
|
+
const coin = tx.coin({
|
|
119
|
+
allowance: { objectId: '0xAllowanceId', funder: '0xFunderAddress' },
|
|
120
|
+
balance: 10_000_000n, // 10 USDC
|
|
121
|
+
type: USDC,
|
|
122
|
+
});
|
|
123
|
+
tx.transferObjects([coin], '0xRecipientAddress');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This skips the SDK's coin type and app binding checks; incorrect references fail on-chain. Building
|
|
127
|
+
may still need a client to resolve object versions and gas.
|
|
128
|
+
|
|
129
|
+
## App-bound allowances
|
|
130
|
+
|
|
131
|
+
App-bound allowances require a `SpendPermit<A>` from the app as well as the spender's signature.
|
|
132
|
+
Pass the permit and app type to `tx.balance()` or `tx.coin()`:
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
|
|
136
|
+
const USDC = '0xUsdcPackage::usdc::USDC';
|
|
137
|
+
const tx = new Transaction();
|
|
138
|
+
const permit = tx.moveCall({
|
|
139
|
+
target: '0xAppPackage::subscriptions::authorize_payment',
|
|
140
|
+
arguments: [tx.object('0xSubscriptionId')],
|
|
141
|
+
});
|
|
142
|
+
const balance = tx.balance({
|
|
143
|
+
balance: 10_000_000n, // 10 USDC
|
|
144
|
+
type: USDC,
|
|
145
|
+
allowance: {
|
|
146
|
+
objectId: '0xAllowanceId',
|
|
147
|
+
app: { type: '0xAppPackage::subscriptions::APP', permit },
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
// Pass balance to the app's next operation.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
To create an app-bound allowance, the funder calls `allowance::propose_for_app`. The app accepts the
|
|
154
|
+
proposal through `allowance::issue` with a `SettingsPermit<A>`.
|
|
155
|
+
|
|
156
|
+
The authorization function and its arguments are defined by the app. The SDK handles the framework's
|
|
157
|
+
`app_balance_spend` call. Add `funder` to the allowance reference to skip the metadata lookup.
|
|
158
|
+
|
|
159
|
+
A permit authorizes one spend but does not bind its amount or recipient. Apps that need to enforce
|
|
160
|
+
those must redeem the withdrawal inside their own Move function, using `tx.withdrawal()` as the
|
|
161
|
+
input.
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
|
|
165
|
+
const tx = new Transaction();
|
|
166
|
+
const withdrawal = tx.withdrawal({
|
|
167
|
+
amount: 10_000_000n,
|
|
168
|
+
type: '0xUsdcPackage::usdc::USDC',
|
|
169
|
+
from: 'allowance',
|
|
170
|
+
allowance: '0xAllowanceId',
|
|
171
|
+
funder: '0xFunderAddress',
|
|
172
|
+
});
|
|
173
|
+
// Pass withdrawal to the app's Move function that redeems it.
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`from: 'allowance'` requires both `allowance` and `funder`; this helper does not look them up.
|
|
@@ -20,7 +20,8 @@ invalidated by other transactions from the same address executing concurrently.
|
|
|
20
20
|
## `tx.coin` and `tx.balance`
|
|
21
21
|
|
|
22
22
|
`tx.coin()` and `tx.balance()` are the recommended ways to get tokens in a transaction. They
|
|
23
|
-
automatically draw from both coin objects and address balances.
|
|
23
|
+
automatically draw from both coin objects and address balances. To spend funds authorized by another
|
|
24
|
+
account, see [Allowances](./allowances.mdx).
|
|
24
25
|
|
|
25
26
|
### Getting a `Coin`
|
|
26
27
|
|
|
@@ -74,11 +75,11 @@ tx.moveCall({
|
|
|
74
75
|
|
|
75
76
|
### Options
|
|
76
77
|
|
|
77
|
-
| Option | Type
|
|
78
|
-
| ------------ |
|
|
79
|
-
| `balance` | `bigint \| number` | _required_ | Amount in base units (MIST for SUI)
|
|
80
|
-
| `type` | `string`
|
|
81
|
-
| `useGasCoin` | `boolean`
|
|
78
|
+
| Option | Type | Default | Description |
|
|
79
|
+
| ------------ | ---------------------------- | ---------- | --------------------------------------------------------------------------------------- |
|
|
80
|
+
| `balance` | `bigint \| number \| string` | _required_ | Amount in base units (MIST for SUI); use safe integer numbers or bigint/decimal strings |
|
|
81
|
+
| `type` | `string` | SUI | Coin type T, not Balance<T>. Defaults to `0x2::sui::SUI` |
|
|
82
|
+
| `useGasCoin` | `boolean` | `true` | For SUI, allow splitting the gas coin. Set `false` for sponsored transactions |
|
|
82
83
|
|
|
83
84
|
For SUI, `tx.coin()` splits from the gas coin by default. For sponsored transactions where the gas
|
|
84
85
|
coin belongs to the sponsor, set `useGasCoin: false`:
|
|
@@ -89,7 +90,7 @@ tx.transferObjects([tx.coin({ balance: 100n, useGasCoin: false })], recipient);
|
|
|
89
90
|
|
|
90
91
|
### `coinWithBalance`
|
|
91
92
|
|
|
92
|
-
`coinWithBalance()` is a standalone
|
|
93
|
+
`coinWithBalance()` is a standalone helper for sender-funded coins:
|
|
93
94
|
|
|
94
95
|
```tsx
|
|
95
96
|
|
|
@@ -100,7 +101,8 @@ tx.transferObjects([coinWithBalance({ balance: 1_000_000_000 })], recipient);
|
|
|
100
101
|
## How resolution works
|
|
101
102
|
|
|
102
103
|
When you call `tx.coin()` or `tx.balance()`, the SDK adds a placeholder intent to the transaction.
|
|
103
|
-
|
|
104
|
+
For sender-funded requests, the resolver replaces it at build time with concrete commands based on
|
|
105
|
+
the sender's funds:
|
|
104
106
|
|
|
105
107
|
- **`tx.balance()` with sufficient address balance:** Uses a direct `FundsWithdrawal` through
|
|
106
108
|
`balance::redeem_funds`. No coin objects are used, so the transaction has no versioned object
|
|
@@ -115,7 +117,8 @@ At build time, the resolver replaces it with concrete commands based on the send
|
|
|
115
117
|
The resolver prefers address balances when possible to avoid introducing versioned object
|
|
116
118
|
dependencies.
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
Sender-funded zero-balance requests resolve to `balance::zero` or `coin::zero` with no network
|
|
121
|
+
lookups.
|
|
119
122
|
|
|
120
123
|
## Checking balances
|
|
121
124
|
|
package/package.json
CHANGED
package/src/bcs/bcs.ts
CHANGED
|
@@ -96,6 +96,10 @@ export const WithdrawalType = bcs.enum('WithdrawalType', {
|
|
|
96
96
|
export const WithdrawFrom = bcs.enum('WithdrawFrom', {
|
|
97
97
|
Sender: null,
|
|
98
98
|
Sponsor: null,
|
|
99
|
+
SenderAllowance: bcs.struct('SenderAllowance', {
|
|
100
|
+
funder: Address,
|
|
101
|
+
allowance: Address,
|
|
102
|
+
}),
|
|
99
103
|
});
|
|
100
104
|
|
|
101
105
|
// Rust: crates/sui-types/src/transaction.rs
|
package/src/bcs/types.ts
CHANGED
|
@@ -44,7 +44,8 @@ export function isPureArg(arg: any): arg is PureArg {
|
|
|
44
44
|
|
|
45
45
|
type Reservation = { MaxAmountU64: number | string };
|
|
46
46
|
type WithdrawalTypeArg = { Balance: TypeTag };
|
|
47
|
-
type WithdrawFrom =
|
|
47
|
+
type WithdrawFrom =
|
|
48
|
+
{ Sender: null } | { Sponsor: null } | { SenderAllowance: { funder: string; allowance: string } };
|
|
48
49
|
type FundsWithdrawalArg = {
|
|
49
50
|
reservation: Reservation;
|
|
50
51
|
typeArg: WithdrawalTypeArg;
|
|
@@ -22,6 +22,9 @@ import { transactionUsesGasCoin } from '../transactions/resolution-utils.js';
|
|
|
22
22
|
// The maximum objects that can be fetched at once using multiGetObjects.
|
|
23
23
|
const MAX_OBJECTS_PER_FETCH = 50;
|
|
24
24
|
|
|
25
|
+
// The gas payment limit is inclusive as of protocol version 96.
|
|
26
|
+
const MAX_GAS_PAYMENT_OBJECTS = 256;
|
|
27
|
+
|
|
25
28
|
// An amount of gas (in gas units) that is added to transactions as an overhead to ensure transactions do not fail.
|
|
26
29
|
const GAS_SAFE_OVERHEAD = 1000n;
|
|
27
30
|
const MAX_GAS = 50_000_000_000;
|
|
@@ -66,10 +69,12 @@ export async function coreClientResolveTransactionPlugin(
|
|
|
66
69
|
for (const input of transactionData.inputs) {
|
|
67
70
|
if (input.$kind !== 'FundsWithdrawal' || !normalizedGasPayer) continue;
|
|
68
71
|
if (normalizeStructTag(input.FundsWithdrawal.typeArg.Balance) !== SUI_TYPE_ARG) continue;
|
|
69
|
-
|
|
70
|
-
const withdrawalOwner =
|
|
71
|
-
?
|
|
72
|
-
:
|
|
72
|
+
const source = input.FundsWithdrawal.withdrawFrom;
|
|
73
|
+
const withdrawalOwner = source.SenderAllowance
|
|
74
|
+
? source.SenderAllowance.funder
|
|
75
|
+
: source.Sender
|
|
76
|
+
? transactionData.sender
|
|
77
|
+
: gasPayer;
|
|
73
78
|
if (
|
|
74
79
|
withdrawalOwner &&
|
|
75
80
|
normalizeSuiAddress(withdrawalOwner) === normalizedGasPayer &&
|
|
@@ -235,12 +240,13 @@ function setGasPayment({
|
|
|
235
240
|
if (usesGasCoin && reservationAmount > 0n && chainIdentifier && epoch) {
|
|
236
241
|
transactionData.gasData.payment = [
|
|
237
242
|
createCoinReservationRef(reservationAmount, gasPayer, chainIdentifier, epoch),
|
|
238
|
-
|
|
243
|
+
// The reservation occupies one entry in the gas payment limit.
|
|
244
|
+
...paymentCoins.slice(0, MAX_GAS_PAYMENT_OBJECTS - 1),
|
|
239
245
|
];
|
|
240
246
|
} else if (!filteredCoins.length) {
|
|
241
247
|
throw new Error('No valid gas coins found for the transaction.');
|
|
242
248
|
} else {
|
|
243
|
-
transactionData.gasData.payment = paymentCoins;
|
|
249
|
+
transactionData.gasData.payment = paymentCoins.slice(0, MAX_GAS_PAYMENT_OBJECTS);
|
|
244
250
|
}
|
|
245
251
|
}
|
|
246
252
|
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
TransactionExpiration_TransactionExpirationKind,
|
|
21
21
|
} from '../grpc/proto/sui/rpc/v2/transaction.js';
|
|
22
22
|
import type { ObjectReference } from '../grpc/proto/sui/rpc/v2/object_reference.js';
|
|
23
|
-
import type { Input } from '../grpc/proto/sui/rpc/v2/input.js';
|
|
23
|
+
import type { FundsWithdrawal, Input } from '../grpc/proto/sui/rpc/v2/input.js';
|
|
24
24
|
import { FundsWithdrawal_Source, Input_InputKind } from '../grpc/proto/sui/rpc/v2/input.js';
|
|
25
25
|
import type { Command } from '../grpc/proto/sui/rpc/v2/transaction.js';
|
|
26
26
|
import type { Argument } from '../grpc/proto/sui/rpc/v2/argument.js';
|
|
@@ -102,10 +102,7 @@ function callArgToGrpcInput(arg: CallArg): Input {
|
|
|
102
102
|
? BigInt(withdrawal.reservation.MaxAmountU64)
|
|
103
103
|
: undefined,
|
|
104
104
|
coinType: withdrawal.typeArg.$kind === 'Balance' ? withdrawal.typeArg.Balance : undefined,
|
|
105
|
-
|
|
106
|
-
withdrawal.withdrawFrom.$kind === 'Sponsor'
|
|
107
|
-
? FundsWithdrawal_Source.SPONSOR
|
|
108
|
-
: FundsWithdrawal_Source.SENDER,
|
|
105
|
+
...tsWithdrawFromToGrpc(withdrawal.withdrawFrom),
|
|
109
106
|
},
|
|
110
107
|
};
|
|
111
108
|
}
|
|
@@ -115,6 +112,46 @@ function callArgToGrpcInput(arg: CallArg): Input {
|
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
|
|
115
|
+
function tsWithdrawFromToGrpc(
|
|
116
|
+
withdrawFrom: Extract<CallArg, { FundsWithdrawal: unknown }>['FundsWithdrawal']['withdrawFrom'],
|
|
117
|
+
): Pick<FundsWithdrawal, 'source' | 'funder' | 'allowance'> {
|
|
118
|
+
switch (withdrawFrom.$kind) {
|
|
119
|
+
case 'Sender':
|
|
120
|
+
return { source: FundsWithdrawal_Source.SENDER };
|
|
121
|
+
case 'Sponsor':
|
|
122
|
+
return { source: FundsWithdrawal_Source.SPONSOR };
|
|
123
|
+
case 'SenderAllowance':
|
|
124
|
+
return {
|
|
125
|
+
source: FundsWithdrawal_Source.SENDER_ALLOWANCE,
|
|
126
|
+
funder: withdrawFrom.SenderAllowance.funder,
|
|
127
|
+
allowance: withdrawFrom.SenderAllowance.allowance,
|
|
128
|
+
};
|
|
129
|
+
default:
|
|
130
|
+
throw new Error(`Unknown WithdrawFrom kind: ${JSON.stringify(withdrawFrom)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function grpcWithdrawFromToTs(
|
|
135
|
+
withdrawal: FundsWithdrawal | undefined,
|
|
136
|
+
): Extract<CallArg, { FundsWithdrawal: unknown }>['FundsWithdrawal']['withdrawFrom'] {
|
|
137
|
+
switch (withdrawal?.source) {
|
|
138
|
+
case FundsWithdrawal_Source.SPONSOR:
|
|
139
|
+
return { $kind: 'Sponsor', Sponsor: true };
|
|
140
|
+
case FundsWithdrawal_Source.SENDER_ALLOWANCE:
|
|
141
|
+
if (!withdrawal.funder || !withdrawal.allowance) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
`SENDER_ALLOWANCE withdrawal is missing funder or allowance: ${JSON.stringify(withdrawal)}`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
$kind: 'SenderAllowance',
|
|
148
|
+
SenderAllowance: { funder: withdrawal.funder, allowance: withdrawal.allowance },
|
|
149
|
+
};
|
|
150
|
+
default:
|
|
151
|
+
return { $kind: 'Sender', Sender: true };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
118
155
|
/**
|
|
119
156
|
* Converts a TypeScript Argument to gRPC Argument
|
|
120
157
|
*/
|
|
@@ -429,10 +466,7 @@ function grpcInputToCallArg(input: Input): CallArg {
|
|
|
429
466
|
$kind: 'Balance' as const,
|
|
430
467
|
Balance: input.fundsWithdrawal?.coinType ?? '0x2::sui::SUI',
|
|
431
468
|
},
|
|
432
|
-
withdrawFrom:
|
|
433
|
-
input.fundsWithdrawal?.source === FundsWithdrawal_Source.SPONSOR
|
|
434
|
-
? { $kind: 'Sponsor' as const, Sponsor: true as const }
|
|
435
|
-
: { $kind: 'Sender' as const, Sender: true as const },
|
|
469
|
+
withdrawFrom: grpcWithdrawFromToTs(input.fundsWithdrawal),
|
|
436
470
|
},
|
|
437
471
|
};
|
|
438
472
|
|