@0xmonaco/core 0.7.3 → 0.7.4
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/dist/api/vault/api.d.ts +40 -31
- package/dist/api/vault/api.js +88 -61
- package/package.json +1 -1
package/dist/api/vault/api.d.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* console.log(`Deposit transaction: ${result.hash}`);
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
import type { ApplicationsAPI, Balance, ProfileAPI, TransactionResult, VaultAPI } from "@0xmonaco/types";
|
|
26
|
+
import type { ApplicationsAPI, Balance, ProfileAPI, TransactionResult, VaultAPI, WithdrawResult } from "@0xmonaco/types";
|
|
27
27
|
import { type Address, type Chain, type PublicClient, type WalletClient } from "viem";
|
|
28
28
|
import { BaseAPI } from "../base";
|
|
29
29
|
export declare class VaultAPIImpl extends BaseAPI implements VaultAPI {
|
|
@@ -148,41 +148,64 @@ export declare class VaultAPIImpl extends BaseAPI implements VaultAPI {
|
|
|
148
148
|
*/
|
|
149
149
|
deposit(assetId: string, amount: bigint, autoWait?: boolean): Promise<TransactionResult>;
|
|
150
150
|
/**
|
|
151
|
-
*
|
|
151
|
+
* Initiates a withdrawal through the API Gateway and submits the resulting
|
|
152
|
+
* pre-signed calldata on-chain via the connected wallet.
|
|
152
153
|
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
154
|
+
* The gateway allocates a `withdrawalIndex` via the matching engine and returns
|
|
155
|
+
* ABI-encoded calldata for `executeSignedWithdrawal(...)` signed by the
|
|
156
|
+
* server-side `WITHDRAWAL_SIGNER`. The user's wallet pays gas to submit it,
|
|
157
|
+
* but the contract authenticates against the embedded signature — not the
|
|
158
|
+
* `msg.sender`. The connected wallet's address is sent as the on-chain
|
|
159
|
+
* `destination`.
|
|
156
160
|
*
|
|
157
161
|
* @param assetId - The asset identifier (UUID) to withdraw
|
|
158
|
-
* @param amount - The
|
|
162
|
+
* @param amount - The raw token amount to withdraw (as bigint)
|
|
159
163
|
* @param autoWait - Whether to automatically wait for transaction confirmation (defaults to true)
|
|
160
|
-
* @returns Promise resolving to
|
|
161
|
-
* @throws {
|
|
162
|
-
* @throws {
|
|
164
|
+
* @returns Promise resolving to `{ withdrawalIndex, transaction }`
|
|
165
|
+
* @throws {APIError} When the asset is not found or the request is rejected
|
|
166
|
+
* @throws {ContractError} When the on-chain submission fails
|
|
163
167
|
* @throws {InvalidConfigError} When wallet account is not available
|
|
164
168
|
*
|
|
165
169
|
* @example
|
|
166
170
|
* ```typescript
|
|
167
|
-
* // Withdraw 50 USDC
|
|
171
|
+
* // Withdraw 50 USDC, wait for on-chain confirmation
|
|
168
172
|
* const result = await vaultAPI.withdraw(
|
|
169
173
|
* "123e4567-e89b-12d3-a456-426614174000",
|
|
170
|
-
* parseUnits("50", 6)
|
|
174
|
+
* parseUnits("50", 6),
|
|
171
175
|
* );
|
|
172
|
-
* console.log(`Withdrawal
|
|
173
|
-
* console.log(`
|
|
176
|
+
* console.log(`Withdrawal index: ${result.withdrawalIndex}`);
|
|
177
|
+
* console.log(`Tx hash: ${result.hash}, status: ${result.status}`);
|
|
174
178
|
*
|
|
175
|
-
* // Or skip auto-waiting
|
|
179
|
+
* // Or skip auto-waiting and finalise later
|
|
176
180
|
* const result = await vaultAPI.withdraw(
|
|
177
181
|
* "123e4567-e89b-12d3-a456-426614174000",
|
|
178
182
|
* parseUnits("50", 6),
|
|
179
|
-
* false
|
|
183
|
+
* false,
|
|
180
184
|
* );
|
|
181
|
-
* // Then manually wait later if needed
|
|
182
185
|
* const receipt = await sdk.waitForTransaction(result.hash);
|
|
183
186
|
* ```
|
|
184
187
|
*/
|
|
185
|
-
withdraw(assetId: string, amount: bigint, autoWait?: boolean): Promise<
|
|
188
|
+
withdraw(assetId: string, amount: bigint, autoWait?: boolean): Promise<WithdrawResult>;
|
|
189
|
+
/**
|
|
190
|
+
* Retries a previously-initiated withdrawal whose on-chain submission never
|
|
191
|
+
* landed — e.g. the wallet rejected the tx, the page reloaded before the
|
|
192
|
+
* receipt came back, or a stuck mempool entry needs resending.
|
|
193
|
+
*
|
|
194
|
+
* Re-fetches the same `executeSignedWithdrawal` calldata the gateway
|
|
195
|
+
* generated when the withdrawal was initiated, then submits it through the
|
|
196
|
+
* connected wallet. Does NOT initiate a new withdrawal — the matching engine
|
|
197
|
+
* already debited the balance and allocated the index. The contract is
|
|
198
|
+
* idempotent against double-submission of a settled withdrawal: it will
|
|
199
|
+
* revert once the index is consumed on-chain.
|
|
200
|
+
*
|
|
201
|
+
* @param withdrawalIndex - The index returned by the original `withdraw()` call
|
|
202
|
+
* @param autoWait - Whether to await on-chain confirmation (defaults to true)
|
|
203
|
+
* @returns Promise resolving to `{ withdrawalIndex, ...transaction }`
|
|
204
|
+
* @throws {APIError} When the index doesn't exist
|
|
205
|
+
* @throws {ContractError} When the on-chain submission fails
|
|
206
|
+
* @throws {InvalidConfigError} When wallet account is not available
|
|
207
|
+
*/
|
|
208
|
+
retryWithdrawal(withdrawalIndex: number, autoWait?: boolean): Promise<WithdrawResult>;
|
|
186
209
|
/**
|
|
187
210
|
* Retrieves the user's token balance in the vault.
|
|
188
211
|
*
|
|
@@ -234,19 +257,5 @@ export declare class VaultAPIImpl extends BaseAPI implements VaultAPI {
|
|
|
234
257
|
* ```
|
|
235
258
|
*/
|
|
236
259
|
needsApproval(assetId: string, amount: bigint): Promise<boolean>;
|
|
237
|
-
/**
|
|
238
|
-
* Retrieves a withdrawal signature from the API Gateway.
|
|
239
|
-
*
|
|
240
|
-
* Internal method that communicates with the Monaco API Gateway to obtain
|
|
241
|
-
* the cryptographic signature required for withdrawal transactions. The signature
|
|
242
|
-
* validates the withdrawal request and ensures proper authorization.
|
|
243
|
-
*
|
|
244
|
-
* @param assetId - The asset identifier (UUID) to withdraw
|
|
245
|
-
* @param amount - The amount to withdraw (as bigint)
|
|
246
|
-
* @returns Promise resolving to object containing seed and signature
|
|
247
|
-
* @throws {APIError} When signature retrieval fails
|
|
248
|
-
* @private
|
|
249
|
-
*/
|
|
250
|
-
private getWithdrawSignature;
|
|
251
260
|
private waitForTransaction;
|
|
252
261
|
}
|
package/dist/api/vault/api.js
CHANGED
|
@@ -275,37 +275,40 @@ export class VaultAPIImpl extends BaseAPI {
|
|
|
275
275
|
return await this.waitForTransaction(txResult, autoWait);
|
|
276
276
|
}
|
|
277
277
|
/**
|
|
278
|
-
*
|
|
278
|
+
* Initiates a withdrawal through the API Gateway and submits the resulting
|
|
279
|
+
* pre-signed calldata on-chain via the connected wallet.
|
|
279
280
|
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
281
|
+
* The gateway allocates a `withdrawalIndex` via the matching engine and returns
|
|
282
|
+
* ABI-encoded calldata for `executeSignedWithdrawal(...)` signed by the
|
|
283
|
+
* server-side `WITHDRAWAL_SIGNER`. The user's wallet pays gas to submit it,
|
|
284
|
+
* but the contract authenticates against the embedded signature — not the
|
|
285
|
+
* `msg.sender`. The connected wallet's address is sent as the on-chain
|
|
286
|
+
* `destination`.
|
|
283
287
|
*
|
|
284
288
|
* @param assetId - The asset identifier (UUID) to withdraw
|
|
285
|
-
* @param amount - The
|
|
289
|
+
* @param amount - The raw token amount to withdraw (as bigint)
|
|
286
290
|
* @param autoWait - Whether to automatically wait for transaction confirmation (defaults to true)
|
|
287
|
-
* @returns Promise resolving to
|
|
288
|
-
* @throws {
|
|
289
|
-
* @throws {
|
|
291
|
+
* @returns Promise resolving to `{ withdrawalIndex, transaction }`
|
|
292
|
+
* @throws {APIError} When the asset is not found or the request is rejected
|
|
293
|
+
* @throws {ContractError} When the on-chain submission fails
|
|
290
294
|
* @throws {InvalidConfigError} When wallet account is not available
|
|
291
295
|
*
|
|
292
296
|
* @example
|
|
293
297
|
* ```typescript
|
|
294
|
-
* // Withdraw 50 USDC
|
|
298
|
+
* // Withdraw 50 USDC, wait for on-chain confirmation
|
|
295
299
|
* const result = await vaultAPI.withdraw(
|
|
296
300
|
* "123e4567-e89b-12d3-a456-426614174000",
|
|
297
|
-
* parseUnits("50", 6)
|
|
301
|
+
* parseUnits("50", 6),
|
|
298
302
|
* );
|
|
299
|
-
* console.log(`Withdrawal
|
|
300
|
-
* console.log(`
|
|
303
|
+
* console.log(`Withdrawal index: ${result.withdrawalIndex}`);
|
|
304
|
+
* console.log(`Tx hash: ${result.hash}, status: ${result.status}`);
|
|
301
305
|
*
|
|
302
|
-
* // Or skip auto-waiting
|
|
306
|
+
* // Or skip auto-waiting and finalise later
|
|
303
307
|
* const result = await vaultAPI.withdraw(
|
|
304
308
|
* "123e4567-e89b-12d3-a456-426614174000",
|
|
305
309
|
* parseUnits("50", 6),
|
|
306
|
-
* false
|
|
310
|
+
* false,
|
|
307
311
|
* );
|
|
308
|
-
* // Then manually wait later if needed
|
|
309
312
|
* const receipt = await sdk.waitForTransaction(result.hash);
|
|
310
313
|
* ```
|
|
311
314
|
*/
|
|
@@ -313,45 +316,95 @@ export class VaultAPIImpl extends BaseAPI {
|
|
|
313
316
|
if (!this.walletClient) {
|
|
314
317
|
throw new InvalidConfigError("Wallet client not set. Connect a wallet first.", "walletClient");
|
|
315
318
|
}
|
|
316
|
-
validate(WithdrawSchema, { assetId, amount, autoWait });
|
|
317
|
-
const vaultAddress = await this.getVaultAddress();
|
|
318
|
-
const { tokenAddress, isNativeToken } = await this.resolveAsset(assetId);
|
|
319
|
-
// Get signature from backend API using asset_id
|
|
320
|
-
const { seed, signature } = await this.getWithdrawSignature(assetId, amount);
|
|
321
319
|
const walletAccount = this.walletClient.account;
|
|
322
320
|
if (!walletAccount) {
|
|
323
321
|
throw new InvalidConfigError("No account available in wallet client", "account");
|
|
324
322
|
}
|
|
325
|
-
|
|
323
|
+
const destination = walletAccount.address.toLowerCase();
|
|
324
|
+
validate(WithdrawSchema, { assetId, amount, destination, autoWait });
|
|
325
|
+
// 1. Gateway allocates withdrawal_index + returns pre-signed
|
|
326
|
+
// executeSignedWithdrawal calldata along with the vault address to send
|
|
327
|
+
// it to. Sourcing the vault address from this response (instead of
|
|
328
|
+
// GET /applications/config) keeps the calldata + target contract in
|
|
329
|
+
// lockstep and avoids an extra round-trip.
|
|
330
|
+
const { withdrawal_index: withdrawalIndex, vault_address: vaultAddress, calldata, } = await this.makeAuthenticatedRequest("/api/v1/withdrawals", {
|
|
331
|
+
method: "POST",
|
|
332
|
+
body: JSON.stringify({
|
|
333
|
+
asset_id: assetId,
|
|
334
|
+
amount: amount.toString(),
|
|
335
|
+
destination,
|
|
336
|
+
}),
|
|
337
|
+
});
|
|
338
|
+
// 2. Submit the calldata on-chain through the connected wallet.
|
|
326
339
|
let hash;
|
|
327
|
-
|
|
328
|
-
hash = await this.walletClient.
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
functionName: "withdrawNative",
|
|
332
|
-
args: [amount, seed, signature],
|
|
340
|
+
try {
|
|
341
|
+
hash = await this.walletClient.sendTransaction({
|
|
342
|
+
to: vaultAddress,
|
|
343
|
+
data: calldata,
|
|
333
344
|
account: walletAccount,
|
|
334
345
|
chain: this.chain,
|
|
335
346
|
});
|
|
336
347
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
348
|
+
catch (error) {
|
|
349
|
+
throw new ContractError(`Failed to submit executeSignedWithdrawal for withdrawal ${withdrawalIndex}: ${error instanceof Error ? error.message : "unknown error"}`, { cause: error instanceof Error ? error : undefined });
|
|
350
|
+
}
|
|
351
|
+
const nonce = walletAccount.getNonce ? await walletAccount.getNonce() : 0n;
|
|
352
|
+
const txResult = {
|
|
353
|
+
hash,
|
|
354
|
+
status: "pending",
|
|
355
|
+
nonce,
|
|
356
|
+
};
|
|
357
|
+
const settled = await this.waitForTransaction(txResult, autoWait);
|
|
358
|
+
return { ...settled, withdrawalIndex };
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Retries a previously-initiated withdrawal whose on-chain submission never
|
|
362
|
+
* landed — e.g. the wallet rejected the tx, the page reloaded before the
|
|
363
|
+
* receipt came back, or a stuck mempool entry needs resending.
|
|
364
|
+
*
|
|
365
|
+
* Re-fetches the same `executeSignedWithdrawal` calldata the gateway
|
|
366
|
+
* generated when the withdrawal was initiated, then submits it through the
|
|
367
|
+
* connected wallet. Does NOT initiate a new withdrawal — the matching engine
|
|
368
|
+
* already debited the balance and allocated the index. The contract is
|
|
369
|
+
* idempotent against double-submission of a settled withdrawal: it will
|
|
370
|
+
* revert once the index is consumed on-chain.
|
|
371
|
+
*
|
|
372
|
+
* @param withdrawalIndex - The index returned by the original `withdraw()` call
|
|
373
|
+
* @param autoWait - Whether to await on-chain confirmation (defaults to true)
|
|
374
|
+
* @returns Promise resolving to `{ withdrawalIndex, ...transaction }`
|
|
375
|
+
* @throws {APIError} When the index doesn't exist
|
|
376
|
+
* @throws {ContractError} When the on-chain submission fails
|
|
377
|
+
* @throws {InvalidConfigError} When wallet account is not available
|
|
378
|
+
*/
|
|
379
|
+
async retryWithdrawal(withdrawalIndex, autoWait = true) {
|
|
380
|
+
if (!this.walletClient) {
|
|
381
|
+
throw new InvalidConfigError("Wallet client not set. Connect a wallet first.", "walletClient");
|
|
382
|
+
}
|
|
383
|
+
const walletAccount = this.walletClient.account;
|
|
384
|
+
if (!walletAccount) {
|
|
385
|
+
throw new InvalidConfigError("No account available in wallet client", "account");
|
|
386
|
+
}
|
|
387
|
+
const { vault_address: vaultAddress, calldata } = await this.makePublicRequest(`/api/v1/withdrawals/${withdrawalIndex}`);
|
|
388
|
+
let hash;
|
|
389
|
+
try {
|
|
390
|
+
hash = await this.walletClient.sendTransaction({
|
|
391
|
+
to: vaultAddress,
|
|
392
|
+
data: calldata,
|
|
343
393
|
account: walletAccount,
|
|
344
394
|
chain: this.chain,
|
|
345
395
|
});
|
|
346
396
|
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
throw new ContractError(`Failed to resubmit executeSignedWithdrawal for withdrawal ${withdrawalIndex}: ${error instanceof Error ? error.message : "unknown error"}`, { cause: error instanceof Error ? error : undefined });
|
|
399
|
+
}
|
|
347
400
|
const nonce = walletAccount.getNonce ? await walletAccount.getNonce() : 0n;
|
|
348
401
|
const txResult = {
|
|
349
402
|
hash,
|
|
350
403
|
status: "pending",
|
|
351
404
|
nonce,
|
|
352
405
|
};
|
|
353
|
-
|
|
354
|
-
return
|
|
406
|
+
const settled = await this.waitForTransaction(txResult, autoWait);
|
|
407
|
+
return { ...settled, withdrawalIndex };
|
|
355
408
|
}
|
|
356
409
|
/**
|
|
357
410
|
* Retrieves the user's token balance in the vault.
|
|
@@ -426,32 +479,6 @@ export class VaultAPIImpl extends BaseAPI {
|
|
|
426
479
|
const allowance = await this.getAllowance(assetId);
|
|
427
480
|
return allowance < amount;
|
|
428
481
|
}
|
|
429
|
-
/**
|
|
430
|
-
* Retrieves a withdrawal signature from the API Gateway.
|
|
431
|
-
*
|
|
432
|
-
* Internal method that communicates with the Monaco API Gateway to obtain
|
|
433
|
-
* the cryptographic signature required for withdrawal transactions. The signature
|
|
434
|
-
* validates the withdrawal request and ensures proper authorization.
|
|
435
|
-
*
|
|
436
|
-
* @param assetId - The asset identifier (UUID) to withdraw
|
|
437
|
-
* @param amount - The amount to withdraw (as bigint)
|
|
438
|
-
* @returns Promise resolving to object containing seed and signature
|
|
439
|
-
* @throws {APIError} When signature retrieval fails
|
|
440
|
-
* @private
|
|
441
|
-
*/
|
|
442
|
-
async getWithdrawSignature(assetId, amount) {
|
|
443
|
-
const data = await this.makeAuthenticatedRequest("/api/v1/withdraw/signature", {
|
|
444
|
-
method: "POST",
|
|
445
|
-
body: JSON.stringify({
|
|
446
|
-
asset_id: assetId,
|
|
447
|
-
amount: amount.toString(),
|
|
448
|
-
}),
|
|
449
|
-
});
|
|
450
|
-
return {
|
|
451
|
-
seed: data.seed,
|
|
452
|
-
signature: data.signature,
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
482
|
async waitForTransaction(txResult, autoWait = true, options = {}) {
|
|
456
483
|
if (!autoWait) {
|
|
457
484
|
return txResult;
|