@keetanetwork/anchor 0.0.37 → 0.0.38
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/lib/queue/index.d.ts +1 -0
- package/lib/queue/index.d.ts.map +1 -1
- package/lib/queue/index.js +16 -0
- package/lib/queue/index.js.map +1 -1
- package/lib/utils/types.d.ts +14 -2
- package/lib/utils/types.d.ts.map +1 -1
- package/lib/utils/types.js.map +1 -1
- package/npm-shrinkwrap.json +5 -5
- package/package.json +2 -2
- package/services/asset-movement/common.d.ts +145 -2
- package/services/asset-movement/common.d.ts.map +1 -1
- package/services/asset-movement/common.js +10 -10
- package/services/asset-movement/common.js.map +1 -1
- package/services/fx/client.d.ts +23 -8
- package/services/fx/client.d.ts.map +1 -1
- package/services/fx/client.js +169 -42
- package/services/fx/client.js.map +1 -1
- package/services/fx/common.d.ts +55 -6
- package/services/fx/common.d.ts.map +1 -1
- package/services/fx/common.js +142 -16
- package/services/fx/common.js.map +1 -1
- package/services/fx/server.d.ts +31 -6
- package/services/fx/server.d.ts.map +1 -1
- package/services/fx/server.js +229 -61
- package/services/fx/server.js.map +1 -1
- package/services/fx/util.d.ts +13 -0
- package/services/fx/util.d.ts.map +1 -0
- package/services/fx/util.js +44 -0
- package/services/fx/util.js.map +1 -0
package/services/fx/server.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as __typia_transform__assertGuard from "typia/lib/internal/_assertGuard.js";
|
|
2
2
|
import * as KeetaAnchorHTTPServer from '../../lib/http-server/index.js';
|
|
3
3
|
import { KeetaNet } from '../../client/index.js';
|
|
4
|
-
import { KeetaAnchorUserError } from '../../lib/error.js';
|
|
5
|
-
import { assertConversionInputCanonicalJSON,
|
|
4
|
+
import { KeetaAnchorError, KeetaAnchorUserError } from '../../lib/error.js';
|
|
5
|
+
import { assertConversionInputCanonicalJSON, assertKeetaFXAnchorClientCreateExchangeRequestJSON, Errors } from './common.js';
|
|
6
6
|
import * as Signing from '../../lib/utils/signing.js';
|
|
7
7
|
import { KeetaAnchorQueueRunner, KeetaAnchorQueueStorageDriverMemory } from '../../lib/queue/index.js';
|
|
8
8
|
import { KeetaAnchorQueuePipelineAdvanced } from '../../lib/queue/pipeline.js';
|
|
9
9
|
import { assertNever } from '../../lib/utils/never.js';
|
|
10
10
|
import * as typia from 'typia';
|
|
11
|
+
import { assertExchangeBlockParameters } from './util.js';
|
|
11
12
|
/**
|
|
12
13
|
* Enable additional runtime "paranoid" checks in the FX server.
|
|
13
14
|
*
|
|
@@ -75,6 +76,31 @@ async function requestToAccounts(config, request) {
|
|
|
75
76
|
signer: signer
|
|
76
77
|
});
|
|
77
78
|
}
|
|
79
|
+
export function toValidateQuoteInput(input) {
|
|
80
|
+
const ret = {
|
|
81
|
+
account: KeetaNet.lib.Account.toAccount(input.account),
|
|
82
|
+
convertedAmount: BigInt(input.convertedAmount),
|
|
83
|
+
cost: {
|
|
84
|
+
amount: BigInt(input.cost.amount),
|
|
85
|
+
token: KeetaNet.lib.Account.toAccount(input.cost.token)
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
if ('convertedAmountBound' in input && input.convertedAmountBound !== undefined) {
|
|
89
|
+
ret.convertedAmountBound = BigInt(input.convertedAmountBound);
|
|
90
|
+
}
|
|
91
|
+
if ('signed' in input && input.signed !== undefined) {
|
|
92
|
+
ret.signed = input.signed;
|
|
93
|
+
}
|
|
94
|
+
if ('request' in input && input.request !== undefined) {
|
|
95
|
+
ret.request = {
|
|
96
|
+
from: KeetaNet.lib.Account.toAccount(input.request.from),
|
|
97
|
+
to: KeetaNet.lib.Account.toAccount(input.request.to),
|
|
98
|
+
amount: BigInt(input.request.amount),
|
|
99
|
+
affinity: input.request.affinity
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return (ret);
|
|
103
|
+
}
|
|
78
104
|
class KeetaFXAnchorQueuePipelineStage1 extends KeetaAnchorQueueRunner {
|
|
79
105
|
serverConfig;
|
|
80
106
|
sequential = true;
|
|
@@ -108,12 +134,17 @@ class KeetaFXAnchorQueuePipelineStage1 extends KeetaAnchorQueueRunner {
|
|
|
108
134
|
*/
|
|
109
135
|
async processor(entry) {
|
|
110
136
|
const { block, expected, request } = entry.request;
|
|
111
|
-
const expectedToken = expected.token;
|
|
112
|
-
const expectedAmount = expected.amount;
|
|
113
137
|
const config = this.serverConfig;
|
|
114
138
|
let userClient;
|
|
115
139
|
if (KeetaNet.UserClient.isInstance(config.client)) {
|
|
116
140
|
userClient = config.client;
|
|
141
|
+
if (!(userClient.account.comparePublicKey(entry.request.account))) {
|
|
142
|
+
return ({
|
|
143
|
+
status: 'failed_permanently',
|
|
144
|
+
output: null,
|
|
145
|
+
error: `Mismatched account for FX request with configured UserClient account`
|
|
146
|
+
});
|
|
147
|
+
}
|
|
117
148
|
}
|
|
118
149
|
else {
|
|
119
150
|
const { signer, account: checkAccount } = await requestToAccounts(config, request);
|
|
@@ -206,7 +237,10 @@ class KeetaFXAnchorQueuePipelineStage1 extends KeetaAnchorQueueRunner {
|
|
|
206
237
|
}
|
|
207
238
|
}
|
|
208
239
|
/* We are clear to attempt the swap now */
|
|
209
|
-
const
|
|
240
|
+
const builder = userClient.initBuilder();
|
|
241
|
+
builder.send(block.account, expected.send.amount, expected.send.token);
|
|
242
|
+
const sendBlock = await builder.computeBlocks();
|
|
243
|
+
const swapBlocks = [...sendBlock.blocks, block];
|
|
210
244
|
const publishOptions = {};
|
|
211
245
|
if (userClient.config.generateFeeBlock !== undefined) {
|
|
212
246
|
publishOptions.generateFeeBlock = userClient.config.generateFeeBlock;
|
|
@@ -233,8 +267,14 @@ class KeetaFXAnchorQueuePipelineStage1 extends KeetaAnchorQueueRunner {
|
|
|
233
267
|
block: Buffer.from(request.block.toBytes()).toString('base64'),
|
|
234
268
|
request: request.request,
|
|
235
269
|
expected: {
|
|
236
|
-
|
|
237
|
-
|
|
270
|
+
receive: {
|
|
271
|
+
token: request.expected.receive.token.publicKeyString.get(),
|
|
272
|
+
amount: request.expected.receive.amount.toString()
|
|
273
|
+
},
|
|
274
|
+
send: {
|
|
275
|
+
token: request.expected.send.token.publicKeyString.get(),
|
|
276
|
+
amount: request.expected.send.amount.toString()
|
|
277
|
+
}
|
|
238
278
|
}
|
|
239
279
|
};
|
|
240
280
|
return (retval);
|
|
@@ -254,8 +294,14 @@ class KeetaFXAnchorQueuePipelineStage1 extends KeetaAnchorQueueRunner {
|
|
|
254
294
|
block: new KeetaNet.lib.Block(reqJSON.block),
|
|
255
295
|
request: reqJSON.request,
|
|
256
296
|
expected: {
|
|
257
|
-
|
|
258
|
-
|
|
297
|
+
receive: {
|
|
298
|
+
token: KeetaNet.lib.Account.fromPublicKeyString(reqJSON.expected.receive.token).assertKeyType(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN),
|
|
299
|
+
amount: BigInt(reqJSON.expected.receive.amount)
|
|
300
|
+
},
|
|
301
|
+
send: {
|
|
302
|
+
token: KeetaNet.lib.Account.fromPublicKeyString(reqJSON.expected.send.token).assertKeyType(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN),
|
|
303
|
+
amount: BigInt(reqJSON.expected.send.amount)
|
|
304
|
+
}
|
|
259
305
|
}
|
|
260
306
|
};
|
|
261
307
|
return (retval);
|
|
@@ -365,6 +411,7 @@ export class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAn
|
|
|
365
411
|
quoteSigner;
|
|
366
412
|
fx;
|
|
367
413
|
pipeline;
|
|
414
|
+
quoteConfiguration;
|
|
368
415
|
pipelineAutoRunInterval = null;
|
|
369
416
|
constructor(config) {
|
|
370
417
|
super(config);
|
|
@@ -372,6 +419,7 @@ export class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAn
|
|
|
372
419
|
this.client = config.client;
|
|
373
420
|
this.fx = config.fx;
|
|
374
421
|
this.quoteSigner = config.quoteSigner;
|
|
422
|
+
this.quoteConfiguration = config.quoteConfiguration ?? { requiresQuote: true };
|
|
375
423
|
/*
|
|
376
424
|
* Setup the accounts
|
|
377
425
|
*/
|
|
@@ -494,23 +542,56 @@ export class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAn
|
|
|
494
542
|
}
|
|
495
543
|
const conversion = assertConversionInputCanonicalJSON(postData.request);
|
|
496
544
|
const rateAndFee = await config.fx.getConversionRateAndFee(conversion);
|
|
545
|
+
let requiresQuoteBody;
|
|
546
|
+
if (instance.quoteConfiguration.requiresQuote) {
|
|
547
|
+
requiresQuoteBody = { requiresQuote: true };
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
if (rateAndFee.convertedAmountBound === undefined) {
|
|
551
|
+
instance.logger.warn('POST /api/getEstimate', 'FX configuration indicates quotes are not required, but "convertedAmountBound" was not provided in the rate and fee response');
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
if (conversion.affinity === 'to' && (BigInt(conversion.amount) > rateAndFee.convertedAmountBound)) {
|
|
555
|
+
throw (new KeetaAnchorError('Affinity is to, but bound is less than estimated sent amount'));
|
|
556
|
+
}
|
|
557
|
+
if (conversion.affinity === 'from' && (BigInt(conversion.amount) < rateAndFee.convertedAmountBound)) {
|
|
558
|
+
throw (new KeetaAnchorError('Affinity is from, but bound is greater than estimated received amount'));
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
requiresQuoteBody = { requiresQuote: false, account: rateAndFee.account };
|
|
562
|
+
}
|
|
497
563
|
const estimateResponse = {
|
|
498
564
|
ok: true,
|
|
499
565
|
estimate: KeetaNet.lib.Utils.Conversion.toJSONSerializable({
|
|
500
566
|
request: conversion,
|
|
501
567
|
convertedAmount: rateAndFee.convertedAmount,
|
|
568
|
+
convertedAmountBound: rateAndFee.convertedAmountBound,
|
|
502
569
|
expectedCost: {
|
|
503
570
|
min: rateAndFee.cost.amount,
|
|
504
571
|
max: rateAndFee.cost.amount,
|
|
505
572
|
token: rateAndFee.cost.token
|
|
506
|
-
}
|
|
573
|
+
},
|
|
574
|
+
...requiresQuoteBody
|
|
507
575
|
})
|
|
508
576
|
};
|
|
509
577
|
return ({
|
|
510
578
|
output: JSON.stringify(estimateResponse)
|
|
511
579
|
});
|
|
512
580
|
};
|
|
581
|
+
async function getUnsignedQuoteData(conversion) {
|
|
582
|
+
const rateAndFee = await config.fx.getConversionRateAndFee(conversion);
|
|
583
|
+
if (PARANOID) {
|
|
584
|
+
const quoteAccount = rateAndFee.account;
|
|
585
|
+
if (!instance.accounts.has(quoteAccount)) {
|
|
586
|
+
throw (new Error('"getConversionRateAndFee" returned an account not configured for this server'));
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return (rateAndFee);
|
|
590
|
+
}
|
|
513
591
|
routes['POST /api/getQuote'] = async function (_ignore_params, postData) {
|
|
592
|
+
if (!instance.quoteConfiguration.requiresQuote && !instance.quoteConfiguration.issueQuotes) {
|
|
593
|
+
throw (new Errors.QuoteIssuanceDisabled());
|
|
594
|
+
}
|
|
514
595
|
if (!postData || typeof postData !== 'object') {
|
|
515
596
|
throw (new Error('No POST data provided'));
|
|
516
597
|
}
|
|
@@ -518,17 +599,14 @@ export class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAn
|
|
|
518
599
|
throw (new Error('POST data missing request'));
|
|
519
600
|
}
|
|
520
601
|
const conversion = assertConversionInputCanonicalJSON(postData.request);
|
|
521
|
-
const rateAndFee = await
|
|
522
|
-
if (PARANOID) {
|
|
523
|
-
const quoteAccount = rateAndFee.account;
|
|
524
|
-
if (!instance.accounts.has(quoteAccount)) {
|
|
525
|
-
throw (new Error('"getConversionRateAndFee" returned an account not configured for this server'));
|
|
526
|
-
}
|
|
527
|
-
}
|
|
602
|
+
const rateAndFee = await getUnsignedQuoteData(conversion);
|
|
528
603
|
const unsignedQuote = KeetaNet.lib.Utils.Conversion.toJSONSerializable({
|
|
529
604
|
request: conversion,
|
|
530
605
|
...rateAndFee
|
|
531
606
|
});
|
|
607
|
+
if (config.quoteSigner === null) {
|
|
608
|
+
throw (new Error('Quote signer not configured, this is required when issuing quotes'));
|
|
609
|
+
}
|
|
532
610
|
const signedQuote = await generateSignedQuote(config.quoteSigner, unsignedQuote);
|
|
533
611
|
const quoteResponse = {
|
|
534
612
|
ok: true,
|
|
@@ -545,64 +623,124 @@ export class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAn
|
|
|
545
623
|
if (!('request' in postData)) {
|
|
546
624
|
throw (new Error('POST data missing request'));
|
|
547
625
|
}
|
|
548
|
-
const request = postData.request;
|
|
549
|
-
if (!request || typeof request !== 'object') {
|
|
550
|
-
throw (new Error('Request is not an object'));
|
|
551
|
-
}
|
|
552
|
-
if (!('quote' in request)) {
|
|
553
|
-
throw (new Error('Quote is missing from request'));
|
|
554
|
-
}
|
|
626
|
+
const request = assertKeetaFXAnchorClientCreateExchangeRequestJSON(postData.request);
|
|
555
627
|
if (!('block' in request) || typeof request.block !== 'string') {
|
|
556
628
|
throw (new Error('Block was not provided in exchange request'));
|
|
557
629
|
}
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
630
|
+
const block = new KeetaNet.lib.Block(request.block);
|
|
631
|
+
let quoteInput;
|
|
632
|
+
let conversionInput;
|
|
633
|
+
let shouldValidateQuote;
|
|
634
|
+
let liquidityAccount;
|
|
635
|
+
if ('quote' in request && 'estimate' in request && request.quote && request.estimate) {
|
|
636
|
+
throw (new Error('Request cannot contain both quote and estimate'));
|
|
637
|
+
}
|
|
638
|
+
else if ('quote' in request && request.quote) {
|
|
639
|
+
shouldValidateQuote = true;
|
|
640
|
+
quoteInput = request.quote;
|
|
641
|
+
conversionInput = quoteInput.request;
|
|
642
|
+
const isValidQuote = await (async () => {
|
|
643
|
+
if (config.quoteSigner === null) {
|
|
644
|
+
return (false);
|
|
645
|
+
}
|
|
646
|
+
return (await verifySignedData(config.quoteSigner, quoteInput));
|
|
647
|
+
})();
|
|
648
|
+
if (!isValidQuote) {
|
|
567
649
|
throw (new Errors.QuoteValidationFailed());
|
|
568
650
|
}
|
|
651
|
+
liquidityAccount = quoteInput.account;
|
|
569
652
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
expectedAmount += BigInt(quote.cost.amount);
|
|
579
|
-
/* If token is different then check block operations for matching amount and token */
|
|
653
|
+
else if ('request' in request && request.request) {
|
|
654
|
+
if (instance.quoteConfiguration.requiresQuote) {
|
|
655
|
+
throw (new Errors.QuoteRequired());
|
|
656
|
+
}
|
|
657
|
+
conversionInput = request.request;
|
|
658
|
+
quoteInput = await getUnsignedQuoteData(conversionInput);
|
|
659
|
+
if (instance.quoteConfiguration.validateQuoteBeforeExchange !== undefined) {
|
|
660
|
+
shouldValidateQuote = instance.quoteConfiguration.validateQuoteBeforeExchange;
|
|
580
661
|
}
|
|
581
662
|
else {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
663
|
+
shouldValidateQuote = config.fx.validateQuote !== undefined;
|
|
664
|
+
}
|
|
665
|
+
for (const operation of block.operations) {
|
|
666
|
+
if (operation.type === KeetaNet.lib.Block.OperationType.SEND) {
|
|
667
|
+
if (!config.accounts) {
|
|
668
|
+
throw (new Error('No accounts configured for FX server, cannot infer liquidity account from block'));
|
|
669
|
+
}
|
|
670
|
+
if (config.accounts.has(operation.to)) {
|
|
671
|
+
liquidityAccount = operation.to;
|
|
672
|
+
break;
|
|
591
673
|
}
|
|
592
674
|
}
|
|
593
|
-
if (!requestIncludesCost) {
|
|
594
|
-
throw (new Error('Exchange missing required cost'));
|
|
595
|
-
}
|
|
596
675
|
}
|
|
676
|
+
if (!liquidityAccount) {
|
|
677
|
+
throw (new KeetaAnchorUserError('Could not determine liquidity account from exchange block'));
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
throw (new Error('Either quote or request must be provided (but not both) in exchange request'));
|
|
682
|
+
}
|
|
683
|
+
const parsedQuote = toValidateQuoteInput(quoteInput);
|
|
684
|
+
/* Validate the quote using the optional callback */
|
|
685
|
+
if (config.fx.validateQuote !== undefined && shouldValidateQuote) {
|
|
686
|
+
const isAcceptable = await config.fx.validateQuote(parsedQuote);
|
|
687
|
+
if (!isAcceptable) {
|
|
688
|
+
throw (new Errors.QuoteValidationFailed());
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
let expectedSendAmount;
|
|
692
|
+
let expectedReceiveAmount;
|
|
693
|
+
if (conversionInput.affinity === 'to') {
|
|
694
|
+
expectedSendAmount = BigInt(conversionInput.amount);
|
|
695
|
+
expectedReceiveAmount = parsedQuote.convertedAmount;
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
expectedSendAmount = parsedQuote.convertedAmount;
|
|
699
|
+
expectedReceiveAmount = BigInt(conversionInput.amount);
|
|
700
|
+
}
|
|
701
|
+
const liquidityAccountInstance = KeetaNet.lib.Account.toAccount(liquidityAccount);
|
|
702
|
+
const userSendsMinimum = { [conversionInput.from]: expectedReceiveAmount };
|
|
703
|
+
const userWillReceiveMaximum = { [conversionInput.to]: expectedSendAmount };
|
|
704
|
+
if (parsedQuote.cost.amount > 0) {
|
|
705
|
+
const feeTokenPub = parsedQuote.cost.token.publicKeyString.get();
|
|
706
|
+
if (!userSendsMinimum[feeTokenPub]) {
|
|
707
|
+
userSendsMinimum[feeTokenPub] = 0n;
|
|
708
|
+
}
|
|
709
|
+
userSendsMinimum[feeTokenPub] += parsedQuote.cost.amount;
|
|
597
710
|
}
|
|
711
|
+
let allowedLiquidityAccounts;
|
|
712
|
+
if (config.accounts) {
|
|
713
|
+
allowedLiquidityAccounts = config.accounts;
|
|
714
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
715
|
+
}
|
|
716
|
+
else if (config.account) {
|
|
717
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
718
|
+
allowedLiquidityAccounts = new KeetaNet.lib.Account.Set([config.account]);
|
|
719
|
+
}
|
|
720
|
+
else {
|
|
721
|
+
throw (new Error('config.account or config.accounts must be provided'));
|
|
722
|
+
}
|
|
723
|
+
assertExchangeBlockParameters({
|
|
724
|
+
block: block,
|
|
725
|
+
liquidityAccount: liquidityAccountInstance,
|
|
726
|
+
allowedLiquidityAccounts: allowedLiquidityAccounts,
|
|
727
|
+
userSendsMinimum: userSendsMinimum,
|
|
728
|
+
userWillReceiveMaximum: userWillReceiveMaximum
|
|
729
|
+
});
|
|
598
730
|
/* Enqueue the exchange request */
|
|
599
731
|
const exchangeID = await instance.pipeline.add({
|
|
600
|
-
account:
|
|
732
|
+
account: liquidityAccountInstance,
|
|
601
733
|
block: block,
|
|
602
|
-
request:
|
|
734
|
+
request: conversionInput,
|
|
603
735
|
expected: {
|
|
604
|
-
|
|
605
|
-
|
|
736
|
+
receive: {
|
|
737
|
+
token: KeetaNet.lib.Account.fromPublicKeyString(conversionInput.from),
|
|
738
|
+
amount: expectedReceiveAmount
|
|
739
|
+
},
|
|
740
|
+
send: {
|
|
741
|
+
token: KeetaNet.lib.Account.fromPublicKeyString(conversionInput.to),
|
|
742
|
+
amount: expectedSendAmount
|
|
743
|
+
}
|
|
606
744
|
}
|
|
607
745
|
});
|
|
608
746
|
const exchangeResponse = {
|
|
@@ -709,7 +847,7 @@ export class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAn
|
|
|
709
847
|
* in a ".generated.ts" file but for simplicity of internal types
|
|
710
848
|
* we keep them here.
|
|
711
849
|
*/
|
|
712
|
-
const assertKeetaFXAnchorQueueStage1RequestJSON = (() => { const _io0 = input => 1 === input.version && "string" === typeof input.account && "string" === typeof input.block && ("object" === typeof input.request && null !== input.request && _io1(input.request)) && ("object" === typeof input.expected && null !== input.expected && _io2(input.expected)); const _io1 = input => "string" === typeof input.from && (RegExp(/^keeta_am(.*)/).test(input.from) || RegExp(/^keeta_an(.*)/).test(input.from) || RegExp(/^keeta_ao(.*)/).test(input.from) || RegExp(/^keeta_ap(.*)/).test(input.from) || RegExp(/^tyblocks_am(.*)/).test(input.from) || RegExp(/^tyblocks_an(.*)/).test(input.from) || RegExp(/^tyblocks_ao(.*)/).test(input.from) || RegExp(/^tyblocks_ap(.*)/).test(input.from)) && ("string" === typeof input.to && (RegExp(/^keeta_am(.*)/).test(input.to) || RegExp(/^keeta_an(.*)/).test(input.to) || RegExp(/^keeta_ao(.*)/).test(input.to) || RegExp(/^keeta_ap(.*)/).test(input.to) || RegExp(/^tyblocks_am(.*)/).test(input.to) || RegExp(/^tyblocks_an(.*)/).test(input.to) || RegExp(/^tyblocks_ao(.*)/).test(input.to) || RegExp(/^tyblocks_ap(.*)/).test(input.to))) && "string" === typeof input.amount && ("from" === input.affinity || "to" === input.affinity); const _io2 = input => "string" === typeof input.token && "string" === typeof input.amount; const _ao0 = (input, _path, _exceptionable = true) => (1 === input.version || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
850
|
+
const assertKeetaFXAnchorQueueStage1RequestJSON = (() => { const _io0 = input => 1 === input.version && "string" === typeof input.account && "string" === typeof input.block && ("object" === typeof input.request && null !== input.request && _io1(input.request)) && ("object" === typeof input.expected && null !== input.expected && _io2(input.expected)); const _io1 = input => "string" === typeof input.from && (RegExp(/^keeta_am(.*)/).test(input.from) || RegExp(/^keeta_an(.*)/).test(input.from) || RegExp(/^keeta_ao(.*)/).test(input.from) || RegExp(/^keeta_ap(.*)/).test(input.from) || RegExp(/^tyblocks_am(.*)/).test(input.from) || RegExp(/^tyblocks_an(.*)/).test(input.from) || RegExp(/^tyblocks_ao(.*)/).test(input.from) || RegExp(/^tyblocks_ap(.*)/).test(input.from)) && ("string" === typeof input.to && (RegExp(/^keeta_am(.*)/).test(input.to) || RegExp(/^keeta_an(.*)/).test(input.to) || RegExp(/^keeta_ao(.*)/).test(input.to) || RegExp(/^keeta_ap(.*)/).test(input.to) || RegExp(/^tyblocks_am(.*)/).test(input.to) || RegExp(/^tyblocks_an(.*)/).test(input.to) || RegExp(/^tyblocks_ao(.*)/).test(input.to) || RegExp(/^tyblocks_ap(.*)/).test(input.to))) && "string" === typeof input.amount && ("from" === input.affinity || "to" === input.affinity); const _io2 = input => "object" === typeof input.receive && null !== input.receive && _io3(input.receive) && ("object" === typeof input.send && null !== input.send && _io4(input.send)); const _io3 = input => "string" === typeof input.token && (RegExp(/^keeta_am(.*)/).test(input.token) || RegExp(/^keeta_an(.*)/).test(input.token) || RegExp(/^keeta_ao(.*)/).test(input.token) || RegExp(/^keeta_ap(.*)/).test(input.token) || RegExp(/^tyblocks_am(.*)/).test(input.token) || RegExp(/^tyblocks_an(.*)/).test(input.token) || RegExp(/^tyblocks_ao(.*)/).test(input.token) || RegExp(/^tyblocks_ap(.*)/).test(input.token)) && "string" === typeof input.amount; const _io4 = input => "string" === typeof input.token && (RegExp(/^keeta_am(.*)/).test(input.token) || RegExp(/^keeta_an(.*)/).test(input.token) || RegExp(/^keeta_ao(.*)/).test(input.token) || RegExp(/^keeta_ap(.*)/).test(input.token) || RegExp(/^tyblocks_am(.*)/).test(input.token) || RegExp(/^tyblocks_an(.*)/).test(input.token) || RegExp(/^tyblocks_ao(.*)/).test(input.token) || RegExp(/^tyblocks_ap(.*)/).test(input.token)) && "string" === typeof input.amount; const _ao0 = (input, _path, _exceptionable = true) => (1 === input.version || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
713
851
|
method: "typia.createAssert",
|
|
714
852
|
path: _path + ".version",
|
|
715
853
|
expected: "1",
|
|
@@ -764,10 +902,40 @@ const assertKeetaFXAnchorQueueStage1RequestJSON = (() => { const _io0 = input =>
|
|
|
764
902
|
path: _path + ".affinity",
|
|
765
903
|
expected: "(\"from\" | \"to\")",
|
|
766
904
|
value: input.affinity
|
|
767
|
-
}, _errorFactory)); const _ao2 = (input, _path, _exceptionable = true) => ("
|
|
905
|
+
}, _errorFactory)); const _ao2 = (input, _path, _exceptionable = true) => (("object" === typeof input.receive && null !== input.receive || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
906
|
+
method: "typia.createAssert",
|
|
907
|
+
path: _path + ".receive",
|
|
908
|
+
expected: "__type.o2",
|
|
909
|
+
value: input.receive
|
|
910
|
+
}, _errorFactory)) && _ao3(input.receive, _path + ".receive", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
911
|
+
method: "typia.createAssert",
|
|
912
|
+
path: _path + ".receive",
|
|
913
|
+
expected: "__type.o2",
|
|
914
|
+
value: input.receive
|
|
915
|
+
}, _errorFactory)) && (("object" === typeof input.send && null !== input.send || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
916
|
+
method: "typia.createAssert",
|
|
917
|
+
path: _path + ".send",
|
|
918
|
+
expected: "__type.o3",
|
|
919
|
+
value: input.send
|
|
920
|
+
}, _errorFactory)) && _ao4(input.send, _path + ".send", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
921
|
+
method: "typia.createAssert",
|
|
922
|
+
path: _path + ".send",
|
|
923
|
+
expected: "__type.o3",
|
|
924
|
+
value: input.send
|
|
925
|
+
}, _errorFactory)); const _ao3 = (input, _path, _exceptionable = true) => ("string" === typeof input.token && (RegExp(/^keeta_am(.*)/).test(input.token) || RegExp(/^keeta_an(.*)/).test(input.token) || RegExp(/^keeta_ao(.*)/).test(input.token) || RegExp(/^keeta_ap(.*)/).test(input.token) || RegExp(/^tyblocks_am(.*)/).test(input.token) || RegExp(/^tyblocks_an(.*)/).test(input.token) || RegExp(/^tyblocks_ao(.*)/).test(input.token) || RegExp(/^tyblocks_ap(.*)/).test(input.token)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
768
926
|
method: "typia.createAssert",
|
|
769
927
|
path: _path + ".token",
|
|
928
|
+
expected: "(`keeta_am${string}` | `keeta_an${string}` | `keeta_ao${string}` | `keeta_ap${string}` | `tyblocks_am${string}` | `tyblocks_an${string}` | `tyblocks_ao${string}` | `tyblocks_ap${string}`)",
|
|
929
|
+
value: input.token
|
|
930
|
+
}, _errorFactory)) && ("string" === typeof input.amount || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
931
|
+
method: "typia.createAssert",
|
|
932
|
+
path: _path + ".amount",
|
|
770
933
|
expected: "string",
|
|
934
|
+
value: input.amount
|
|
935
|
+
}, _errorFactory)); const _ao4 = (input, _path, _exceptionable = true) => ("string" === typeof input.token && (RegExp(/^keeta_am(.*)/).test(input.token) || RegExp(/^keeta_an(.*)/).test(input.token) || RegExp(/^keeta_ao(.*)/).test(input.token) || RegExp(/^keeta_ap(.*)/).test(input.token) || RegExp(/^tyblocks_am(.*)/).test(input.token) || RegExp(/^tyblocks_an(.*)/).test(input.token) || RegExp(/^tyblocks_ao(.*)/).test(input.token) || RegExp(/^tyblocks_ap(.*)/).test(input.token)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
936
|
+
method: "typia.createAssert",
|
|
937
|
+
path: _path + ".token",
|
|
938
|
+
expected: "(`keeta_am${string}` | `keeta_an${string}` | `keeta_ao${string}` | `keeta_ap${string}` | `tyblocks_am${string}` | `tyblocks_an${string}` | `tyblocks_ao${string}` | `tyblocks_ap${string}`)",
|
|
771
939
|
value: input.token
|
|
772
940
|
}, _errorFactory)) && ("string" === typeof input.amount || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
773
941
|
method: "typia.createAssert",
|