@ar.io/sdk 3.23.0-alpha.6 → 3.23.0-alpha.7
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.
|
@@ -297,7 +297,9 @@ class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
297
297
|
}
|
|
298
298
|
async listNameForSale({ name, expirationTime, price, type, walletAddress, minimumPrice, decreaseInterval, onProgress = (event) => {
|
|
299
299
|
this.logger.info(`List name for sale progress: ${event.step}`);
|
|
300
|
-
}, }) {
|
|
300
|
+
}, }, timeoutOptions) {
|
|
301
|
+
const maxRetries = timeoutOptions?.maxRetries ?? 15;
|
|
302
|
+
const statusPollIntervalMs = timeoutOptions?.statusPollIntervalMs ?? 3000;
|
|
301
303
|
// Get arns record for the current ant id associated with it
|
|
302
304
|
const record = await this.ario.getArNSRecord({ name: name });
|
|
303
305
|
this.logger.info(`Record ${name} found: ${JSON.stringify(record)}`);
|
|
@@ -357,10 +359,26 @@ class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
357
359
|
// check error for existing intent. Will be a contract error message.
|
|
358
360
|
const isExistingIntentError = error.message.includes('An intent already exists for this ANT ID');
|
|
359
361
|
if (isExistingIntentError) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
+
let fetchedIntent;
|
|
363
|
+
let lastIntentError = null;
|
|
364
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
365
|
+
try {
|
|
366
|
+
fetchedIntent = await this.getIntentByANTId(antId);
|
|
367
|
+
lastIntentError = null;
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
catch (getIntentError) {
|
|
371
|
+
lastIntentError = getIntentError;
|
|
372
|
+
this.logger.error(`Failed to get intent (attempt ${attempt + 1}/${maxRetries + 1}): ${getIntentError.message}`);
|
|
373
|
+
if (attempt < maxRetries) {
|
|
374
|
+
const backoffMs = statusPollIntervalMs * Math.pow(2, attempt);
|
|
375
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (lastIntentError !== null || fetchedIntent === undefined) {
|
|
362
380
|
const intentError = new Error('An intent already exists for this ANT ID but failed to get intent:\n\n' +
|
|
363
|
-
|
|
381
|
+
(lastIntentError?.message ?? 'Unknown error'));
|
|
364
382
|
onProgress({
|
|
365
383
|
step: 'error',
|
|
366
384
|
name,
|
|
@@ -369,7 +387,8 @@ class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
369
387
|
failedStep: 'creating-intent',
|
|
370
388
|
});
|
|
371
389
|
throw intentError;
|
|
372
|
-
}
|
|
390
|
+
}
|
|
391
|
+
intent = fetchedIntent;
|
|
373
392
|
}
|
|
374
393
|
else {
|
|
375
394
|
// Possible to get other errors, eg insufficient deposited ario balance. Rethrow them here.
|
|
@@ -407,12 +426,32 @@ class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
407
426
|
step: 'transferring-ant',
|
|
408
427
|
...transferAntEventData,
|
|
409
428
|
});
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
429
|
+
let transferResult;
|
|
430
|
+
let lastTransferError = null;
|
|
431
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
432
|
+
try {
|
|
433
|
+
transferResult = await ant.transfer({
|
|
434
|
+
target: this.process.processId,
|
|
435
|
+
removeControllers: false, // important: do not remove the controllers of the ANT to prevent loss of control
|
|
436
|
+
}, {
|
|
437
|
+
tags: [{ name: 'X-Intent-Id', value: intent.intentId }],
|
|
438
|
+
});
|
|
439
|
+
lastTransferError = null;
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
lastTransferError = error;
|
|
444
|
+
this.logger.error(`Failed to transfer ANT (attempt ${attempt + 1}/${maxRetries + 1}): ${error.message}`);
|
|
445
|
+
if (attempt < maxRetries) {
|
|
446
|
+
const backoffMs = statusPollIntervalMs * Math.pow(2, attempt);
|
|
447
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (lastTransferError !== null || transferResult === undefined) {
|
|
452
|
+
throw lastTransferError ?? new Error('Failed to transfer ANT');
|
|
453
|
+
}
|
|
454
|
+
antTransferResult = transferResult;
|
|
416
455
|
this.logger.info(`ANT transferred: ${JSON.stringify(antTransferResult)}`);
|
|
417
456
|
onProgress({
|
|
418
457
|
step: 'ant-transferred',
|
|
@@ -441,24 +480,20 @@ class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
441
480
|
// This is to ensure the order is created before returning the result for ux purposes.
|
|
442
481
|
// This may still fail, in which case we return the intent and ant transfer result and handle the error in the client.
|
|
443
482
|
let order = null;
|
|
444
|
-
let
|
|
445
|
-
while (order === null && tries < 5) {
|
|
483
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
446
484
|
try {
|
|
447
485
|
order = await this.getOrderByANTId(antId).catch((error) => {
|
|
448
|
-
|
|
486
|
+
this.logger.warn(`Failed to get order: ${error.message}`);
|
|
449
487
|
return null;
|
|
450
488
|
});
|
|
451
|
-
if (order
|
|
452
|
-
|
|
489
|
+
if (order !== null) {
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
if (attempt < maxRetries) {
|
|
453
493
|
this.logger.info(`Waiting for order to be created...`);
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
throw new Error(`Failed to get order after ${tries} attempts`);
|
|
457
|
-
}
|
|
458
|
-
tries++;
|
|
494
|
+
const backoffMs = statusPollIntervalMs * Math.pow(2, attempt);
|
|
495
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
459
496
|
}
|
|
460
|
-
// if the order is found, break the loop
|
|
461
|
-
break;
|
|
462
497
|
}
|
|
463
498
|
catch (error) {
|
|
464
499
|
this.logger.error(`Failed to get order: ${error.message}`);
|
package/lib/cjs/version.js
CHANGED
|
@@ -291,7 +291,9 @@ export class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
291
291
|
}
|
|
292
292
|
async listNameForSale({ name, expirationTime, price, type, walletAddress, minimumPrice, decreaseInterval, onProgress = (event) => {
|
|
293
293
|
this.logger.info(`List name for sale progress: ${event.step}`);
|
|
294
|
-
}, }) {
|
|
294
|
+
}, }, timeoutOptions) {
|
|
295
|
+
const maxRetries = timeoutOptions?.maxRetries ?? 15;
|
|
296
|
+
const statusPollIntervalMs = timeoutOptions?.statusPollIntervalMs ?? 3000;
|
|
295
297
|
// Get arns record for the current ant id associated with it
|
|
296
298
|
const record = await this.ario.getArNSRecord({ name: name });
|
|
297
299
|
this.logger.info(`Record ${name} found: ${JSON.stringify(record)}`);
|
|
@@ -351,10 +353,26 @@ export class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
351
353
|
// check error for existing intent. Will be a contract error message.
|
|
352
354
|
const isExistingIntentError = error.message.includes('An intent already exists for this ANT ID');
|
|
353
355
|
if (isExistingIntentError) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
+
let fetchedIntent;
|
|
357
|
+
let lastIntentError = null;
|
|
358
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
359
|
+
try {
|
|
360
|
+
fetchedIntent = await this.getIntentByANTId(antId);
|
|
361
|
+
lastIntentError = null;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
catch (getIntentError) {
|
|
365
|
+
lastIntentError = getIntentError;
|
|
366
|
+
this.logger.error(`Failed to get intent (attempt ${attempt + 1}/${maxRetries + 1}): ${getIntentError.message}`);
|
|
367
|
+
if (attempt < maxRetries) {
|
|
368
|
+
const backoffMs = statusPollIntervalMs * Math.pow(2, attempt);
|
|
369
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (lastIntentError !== null || fetchedIntent === undefined) {
|
|
356
374
|
const intentError = new Error('An intent already exists for this ANT ID but failed to get intent:\n\n' +
|
|
357
|
-
|
|
375
|
+
(lastIntentError?.message ?? 'Unknown error'));
|
|
358
376
|
onProgress({
|
|
359
377
|
step: 'error',
|
|
360
378
|
name,
|
|
@@ -363,7 +381,8 @@ export class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
363
381
|
failedStep: 'creating-intent',
|
|
364
382
|
});
|
|
365
383
|
throw intentError;
|
|
366
|
-
}
|
|
384
|
+
}
|
|
385
|
+
intent = fetchedIntent;
|
|
367
386
|
}
|
|
368
387
|
else {
|
|
369
388
|
// Possible to get other errors, eg insufficient deposited ario balance. Rethrow them here.
|
|
@@ -401,12 +420,32 @@ export class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
401
420
|
step: 'transferring-ant',
|
|
402
421
|
...transferAntEventData,
|
|
403
422
|
});
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
423
|
+
let transferResult;
|
|
424
|
+
let lastTransferError = null;
|
|
425
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
426
|
+
try {
|
|
427
|
+
transferResult = await ant.transfer({
|
|
428
|
+
target: this.process.processId,
|
|
429
|
+
removeControllers: false, // important: do not remove the controllers of the ANT to prevent loss of control
|
|
430
|
+
}, {
|
|
431
|
+
tags: [{ name: 'X-Intent-Id', value: intent.intentId }],
|
|
432
|
+
});
|
|
433
|
+
lastTransferError = null;
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
lastTransferError = error;
|
|
438
|
+
this.logger.error(`Failed to transfer ANT (attempt ${attempt + 1}/${maxRetries + 1}): ${error.message}`);
|
|
439
|
+
if (attempt < maxRetries) {
|
|
440
|
+
const backoffMs = statusPollIntervalMs * Math.pow(2, attempt);
|
|
441
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (lastTransferError !== null || transferResult === undefined) {
|
|
446
|
+
throw lastTransferError ?? new Error('Failed to transfer ANT');
|
|
447
|
+
}
|
|
448
|
+
antTransferResult = transferResult;
|
|
410
449
|
this.logger.info(`ANT transferred: ${JSON.stringify(antTransferResult)}`);
|
|
411
450
|
onProgress({
|
|
412
451
|
step: 'ant-transferred',
|
|
@@ -435,24 +474,20 @@ export class ArNSMarketplaceWrite extends ArNSMarketplaceRead {
|
|
|
435
474
|
// This is to ensure the order is created before returning the result for ux purposes.
|
|
436
475
|
// This may still fail, in which case we return the intent and ant transfer result and handle the error in the client.
|
|
437
476
|
let order = null;
|
|
438
|
-
let
|
|
439
|
-
while (order === null && tries < 5) {
|
|
477
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
440
478
|
try {
|
|
441
479
|
order = await this.getOrderByANTId(antId).catch((error) => {
|
|
442
|
-
|
|
480
|
+
this.logger.warn(`Failed to get order: ${error.message}`);
|
|
443
481
|
return null;
|
|
444
482
|
});
|
|
445
|
-
if (order
|
|
446
|
-
|
|
483
|
+
if (order !== null) {
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
if (attempt < maxRetries) {
|
|
447
487
|
this.logger.info(`Waiting for order to be created...`);
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
throw new Error(`Failed to get order after ${tries} attempts`);
|
|
451
|
-
}
|
|
452
|
-
tries++;
|
|
488
|
+
const backoffMs = statusPollIntervalMs * Math.pow(2, attempt);
|
|
489
|
+
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
453
490
|
}
|
|
454
|
-
// if the order is found, break the loop
|
|
455
|
-
break;
|
|
456
491
|
}
|
|
457
492
|
catch (error) {
|
|
458
493
|
this.logger.error(`Failed to get order: ${error.message}`);
|
package/lib/esm/version.js
CHANGED
|
@@ -301,6 +301,17 @@ export interface ListNameForSaleCompleteEvent {
|
|
|
301
301
|
* @experimental
|
|
302
302
|
*/
|
|
303
303
|
export type ListNameForSaleProgressEvent = CreatingIntentProgressEvent | IntentCreatedProgressEvent | TransferringAntProgressEvent | AntTransferredProgressEvent | ListNameForSaleErrorEvent | ListNameForSaleCompleteEvent;
|
|
304
|
+
/**
|
|
305
|
+
* Timeout and retry options for listNameForSale status checks and polling.
|
|
306
|
+
* Used when checking for intent (e.g. getIntentByANTId), transfer confirmation, and order listing.
|
|
307
|
+
* @experimental
|
|
308
|
+
*/
|
|
309
|
+
export interface ListNameForSaleTimeoutOptions {
|
|
310
|
+
/** Max retries when polling for intent, transfer confirmation, or order listing. Default 5. */
|
|
311
|
+
maxRetries?: number;
|
|
312
|
+
/** Base interval in ms for exponential backoff between status polls / retries. Wait time is base * 2^attempt. Default 1000. */
|
|
313
|
+
statusPollIntervalMs?: number;
|
|
314
|
+
}
|
|
304
315
|
/**
|
|
305
316
|
* Write interface for the ArNS marketplace
|
|
306
317
|
* @experimental
|
|
@@ -328,6 +339,7 @@ export interface AoArNSMarketplaceWrite {
|
|
|
328
339
|
/**
|
|
329
340
|
* List a name for sale on the marketplace
|
|
330
341
|
* @param params - Parameters including name, expiration time, price, type, wallet address, and optional auction parameters
|
|
342
|
+
* @param timeoutOptions - Optional retries and wait times for intent, transfer, and order listing status polling
|
|
331
343
|
* @returns Result containing intent, order, ANT transfer result, and any error
|
|
332
344
|
*/
|
|
333
345
|
listNameForSale({ name, expirationTime, price, type, walletAddress, minimumPrice, decreaseInterval, onProgress, }: {
|
|
@@ -339,7 +351,7 @@ export interface AoArNSMarketplaceWrite {
|
|
|
339
351
|
minimumPrice?: string;
|
|
340
352
|
decreaseInterval?: string;
|
|
341
353
|
onProgress?: (event: ListNameForSaleProgressEvent) => void;
|
|
342
|
-
}): Promise<{
|
|
354
|
+
}, timeoutOptions?: ListNameForSaleTimeoutOptions): Promise<{
|
|
343
355
|
intent: MarketplaceIntent;
|
|
344
356
|
order: Order | null;
|
|
345
357
|
antTransferResult: AoMessageResult<Record<string, string | number | boolean | null>> | null;
|
|
@@ -473,7 +485,7 @@ export declare class ArNSMarketplaceWrite extends ArNSMarketplaceRead implements
|
|
|
473
485
|
minimumPrice?: string;
|
|
474
486
|
decreaseInterval?: string;
|
|
475
487
|
onProgress?: (event: ListNameForSaleProgressEvent) => void;
|
|
476
|
-
}): Promise<{
|
|
488
|
+
}, timeoutOptions?: ListNameForSaleTimeoutOptions): Promise<{
|
|
477
489
|
intent: MarketplaceIntent;
|
|
478
490
|
order: Order | null;
|
|
479
491
|
antTransferResult: AoMessageResult<Record<string, string | number | boolean | null>> | null;
|
package/lib/types/version.d.ts
CHANGED