@keetanetwork/anchor 0.0.3 → 0.0.6
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/client/index.d.ts +6 -0
- package/client/index.d.ts.map +1 -1
- package/client/index.js +7 -0
- package/client/index.js.map +1 -1
- package/lib/error.d.ts +14 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +38 -0
- package/lib/error.js.map +1 -0
- package/lib/http-server.d.ts +59 -0
- package/lib/http-server.d.ts.map +1 -0
- package/lib/http-server.js +383 -0
- package/lib/http-server.js.map +1 -0
- package/lib/resolver.d.ts +159 -60
- package/lib/resolver.d.ts.map +1 -1
- package/lib/resolver.js +3519 -384
- package/lib/resolver.js.map +1 -1
- package/lib/utils/brand.d.ts +12 -0
- package/lib/utils/brand.d.ts.map +1 -0
- package/lib/utils/brand.js +2 -0
- package/lib/utils/brand.js.map +1 -0
- package/lib/utils/never.d.ts +4 -0
- package/lib/utils/never.d.ts.map +1 -1
- package/lib/utils/never.js.map +1 -1
- package/lib/utils/signing.d.ts +17 -0
- package/lib/utils/signing.d.ts.map +1 -0
- package/lib/utils/signing.js +73 -0
- package/lib/utils/signing.js.map +1 -0
- package/lib/utils/url.d.ts +2 -0
- package/lib/utils/url.d.ts.map +1 -0
- package/lib/utils/url.js +8 -0
- package/lib/utils/url.js.map +1 -0
- package/npm-shrinkwrap.json +529 -16210
- package/package.json +31 -40
- package/services/fx/client.d.ts +137 -0
- package/services/fx/client.d.ts.map +1 -0
- package/services/fx/client.js +519 -0
- package/services/fx/client.js.map +1 -0
- package/services/fx/common.d.ts +133 -0
- package/services/fx/common.d.ts.map +1 -0
- package/services/fx/common.js +45 -0
- package/services/fx/common.js.map +1 -0
- package/services/fx/server.d.ts +58 -0
- package/services/fx/server.d.ts.map +1 -0
- package/services/fx/server.js +349 -0
- package/services/fx/server.js.map +1 -0
- package/services/kyc/client.d.ts +1 -1
- package/services/kyc/client.d.ts.map +1 -1
- package/services/kyc/client.js +7 -53
- package/services/kyc/client.js.map +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { lib as KeetaNetLib, type UserClient as KeetaNetUserClient } from '@keetanetwork/keetanet-client';
|
|
2
|
+
import type { Decimal } from 'decimal.js';
|
|
3
|
+
import type { ServiceSearchCriteria } from '../../lib/resolver.js';
|
|
4
|
+
export type KeetaNetAccount = InstanceType<typeof KeetaNetLib.Account>;
|
|
5
|
+
export type KeetaNetToken = InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN>>;
|
|
6
|
+
export type KeetaNetTokenPublicKeyString = ReturnType<InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN>>['publicKeyString']['get']>;
|
|
7
|
+
export type ConversionInput = {
|
|
8
|
+
/**
|
|
9
|
+
* The currency code to convert from (i.e., what the user has).
|
|
10
|
+
*/
|
|
11
|
+
from: ServiceSearchCriteria<'fx'>['inputCurrencyCode'] | KeetaNetToken;
|
|
12
|
+
/**
|
|
13
|
+
* The currency code to convert to (i.e., what the user wants).
|
|
14
|
+
*/
|
|
15
|
+
to: ServiceSearchCriteria<'fx'>['outputCurrencyCode'] | KeetaNetToken;
|
|
16
|
+
/**
|
|
17
|
+
* The amount to convert. This is a string or Decimal representing the
|
|
18
|
+
* amount in the currency specified by either `from` or `to`, as
|
|
19
|
+
* specified by the `affinity` property.
|
|
20
|
+
*/
|
|
21
|
+
amount: string | number | Decimal;
|
|
22
|
+
/**
|
|
23
|
+
* Indicates whether the amount specified is in terms of the `from`
|
|
24
|
+
* currency (i.e., the user has this much) or the `to` currency
|
|
25
|
+
* (i.e., the user wants this much).
|
|
26
|
+
*/
|
|
27
|
+
affinity: 'from' | 'to';
|
|
28
|
+
};
|
|
29
|
+
export type ConversionInputCanonical = {
|
|
30
|
+
[k in keyof ConversionInput]: k extends 'amount' ? string : k extends 'from' ? KeetaNetTokenPublicKeyString : k extends 'to' ? KeetaNetTokenPublicKeyString : ConversionInput[k];
|
|
31
|
+
};
|
|
32
|
+
export type KeetaFXAnchorClientCreateExchangeRequest = {
|
|
33
|
+
quote: KeetaFXAnchorQuote;
|
|
34
|
+
block: InstanceType<typeof KeetaNetLib.Block>;
|
|
35
|
+
};
|
|
36
|
+
export type KeetaFXAnchorClientGetExchangeStatusRequest = {
|
|
37
|
+
exchangeID: string;
|
|
38
|
+
};
|
|
39
|
+
export type KeetaFXAnchorEstimate = {
|
|
40
|
+
/**
|
|
41
|
+
* Conversion request that was provided
|
|
42
|
+
*/
|
|
43
|
+
request: ConversionInputCanonical;
|
|
44
|
+
/**
|
|
45
|
+
* Amount after the conversion as specified by either `from` or `to`, as specified by the `affinity` property in the request.
|
|
46
|
+
*/
|
|
47
|
+
convertedAmount: string;
|
|
48
|
+
/**
|
|
49
|
+
* The expected cost of the fx request, in the form of a
|
|
50
|
+
* token and a range of minimum and maximum expected costs
|
|
51
|
+
*/
|
|
52
|
+
expectedCost: {
|
|
53
|
+
min: string;
|
|
54
|
+
max: string;
|
|
55
|
+
token: KeetaNetTokenPublicKeyString;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export type KeetaFXAnchorEstimateResponse = ({
|
|
59
|
+
ok: true;
|
|
60
|
+
estimate: KeetaFXAnchorEstimate;
|
|
61
|
+
} | {
|
|
62
|
+
ok: false;
|
|
63
|
+
error: string;
|
|
64
|
+
});
|
|
65
|
+
export type KeetaFXAnchorQuote = {
|
|
66
|
+
/**
|
|
67
|
+
* Conversion request that was provided
|
|
68
|
+
*/
|
|
69
|
+
request: ConversionInputCanonical;
|
|
70
|
+
/**
|
|
71
|
+
* The public key of the liquidity provider account
|
|
72
|
+
*/
|
|
73
|
+
account: string;
|
|
74
|
+
/**
|
|
75
|
+
* Amount after the conversion as specified by either `from` or `to`, as specified by the `affinity` property in the request.
|
|
76
|
+
*/
|
|
77
|
+
convertedAmount: string;
|
|
78
|
+
/**
|
|
79
|
+
* The cost of the fx request, in the form of a
|
|
80
|
+
* token and amount that should be included with the swap
|
|
81
|
+
*/
|
|
82
|
+
cost: {
|
|
83
|
+
amount: string;
|
|
84
|
+
token: KeetaNetTokenPublicKeyString;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Signature information to verify the quote
|
|
88
|
+
*/
|
|
89
|
+
signed: {
|
|
90
|
+
nonce: string;
|
|
91
|
+
timestamp: string;
|
|
92
|
+
signature: string;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
export type KeetaFXAnchorQuoteResponse = ({
|
|
96
|
+
ok: true;
|
|
97
|
+
quote: KeetaFXAnchorQuote;
|
|
98
|
+
} | {
|
|
99
|
+
ok: false;
|
|
100
|
+
error: string;
|
|
101
|
+
});
|
|
102
|
+
export type KeetaFXAnchorExchange = {
|
|
103
|
+
/**
|
|
104
|
+
* ID used to identify the conversion request
|
|
105
|
+
*/
|
|
106
|
+
exchangeID: string;
|
|
107
|
+
};
|
|
108
|
+
export type KeetaFXAnchorExchangeResponse = KeetaFXAnchorExchange & ({
|
|
109
|
+
ok: true;
|
|
110
|
+
} | {
|
|
111
|
+
ok: false;
|
|
112
|
+
error: string;
|
|
113
|
+
});
|
|
114
|
+
/**
|
|
115
|
+
* @deprecated Use the Node UserClient methods in the future instead of this function
|
|
116
|
+
*/
|
|
117
|
+
export declare function createSwapRequest(userClient: KeetaNetUserClient, from: {
|
|
118
|
+
account: KeetaNetAccount;
|
|
119
|
+
token: KeetaNetToken;
|
|
120
|
+
amount: bigint;
|
|
121
|
+
}, to: {
|
|
122
|
+
account: KeetaNetAccount;
|
|
123
|
+
token: KeetaNetToken;
|
|
124
|
+
amount: bigint;
|
|
125
|
+
}): Promise<InstanceType<typeof KeetaNetLib.Block>>;
|
|
126
|
+
/**
|
|
127
|
+
* @deprecated Use the Node UserClient methods in the future instead of this function
|
|
128
|
+
*/
|
|
129
|
+
export declare function acceptSwapRequest(userClient: KeetaNetUserClient, request: InstanceType<typeof KeetaNetLib.Block>, expected: {
|
|
130
|
+
token?: KeetaNetToken;
|
|
131
|
+
amount?: bigint;
|
|
132
|
+
}): Promise<InstanceType<typeof KeetaNetLib.Block>[]>;
|
|
133
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/services/fx/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated Use the Node UserClient methods in the future instead of this function
|
|
4
|
+
*/
|
|
5
|
+
export async function createSwapRequest(userClient, from, to) {
|
|
6
|
+
const builder = userClient.initBuilder();
|
|
7
|
+
builder.send(to.account, from.amount, from.token);
|
|
8
|
+
builder.receive(to.account, to.amount, to.token, true);
|
|
9
|
+
const blocks = await builder.computeBlocks();
|
|
10
|
+
if (blocks.blocks.length !== 1) {
|
|
11
|
+
throw (new Error('Compute Swap Request Generated more than 1 block'));
|
|
12
|
+
}
|
|
13
|
+
const block = blocks.blocks[0];
|
|
14
|
+
if (block === undefined) {
|
|
15
|
+
throw (new Error('Swap Block is undefined'));
|
|
16
|
+
}
|
|
17
|
+
return (block);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Use the Node UserClient methods in the future instead of this function
|
|
21
|
+
*/
|
|
22
|
+
export async function acceptSwapRequest(userClient, request, expected) {
|
|
23
|
+
const builder = userClient.initBuilder();
|
|
24
|
+
const sendOperation = request.operations.find(({ type }) => KeetaNetLib.Block.OperationType.SEND === type);
|
|
25
|
+
if (!sendOperation || sendOperation.type !== KeetaNetLib.Block.OperationType.SEND) {
|
|
26
|
+
throw (new Error('Swap Request is missing send'));
|
|
27
|
+
}
|
|
28
|
+
if (!sendOperation.to.comparePublicKey(userClient.account)) {
|
|
29
|
+
throw (new Error(`Swap Request send account does not match`));
|
|
30
|
+
}
|
|
31
|
+
if (expected.token !== undefined && !sendOperation.token.comparePublicKey(expected.token)) {
|
|
32
|
+
throw (new Error('Swap Request send token does not match expected'));
|
|
33
|
+
}
|
|
34
|
+
if (expected.amount !== undefined && sendOperation.amount !== expected.amount) {
|
|
35
|
+
throw (new Error(`Swap Request send amount ${sendOperation.amount} does not match expected amount ${expected.amount}`));
|
|
36
|
+
}
|
|
37
|
+
const receiveOperation = request.operations.find(({ type }) => KeetaNetLib.Block.OperationType.RECEIVE === type);
|
|
38
|
+
if (!receiveOperation || receiveOperation.type !== KeetaNetLib.Block.OperationType.RECEIVE) {
|
|
39
|
+
throw (new Error("Swap Request is missing receive operation"));
|
|
40
|
+
}
|
|
41
|
+
builder.send(request.account, receiveOperation.amount, receiveOperation.token);
|
|
42
|
+
const blocks = await builder.computeBlocks();
|
|
43
|
+
return ([...blocks.blocks, request]);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/services/fx/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,WAAW,EAAyC,MAAO,+BAA+B,CAAC;AAwI3G;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAA8B,EAAE,IAAwE,EAAE,EAAsE;IACvN,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IACzC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACtD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;IAE7C,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,MAAK,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,MAAK,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,OAAM,CAAC,KAAK,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAA8B,EAAE,OAA+C,EAAE,QAAoD;IAC5K,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IAEzC,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC3G,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,KAAK,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QACnF,MAAK,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,MAAK,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3F,MAAK,CAAC,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC,CAAA;IACpE,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,IAAI,aAAa,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC/E,MAAK,CAAC,IAAI,KAAK,CAAC,4BAA4B,aAAa,CAAC,MAAM,mCAAmC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACvH,CAAC;IAED,MAAM,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;IACjH,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,KAAK,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QAC5F,MAAK,CAAC,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAE/E,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;IAC7C,OAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { lib as KeetaNetLib, type UserClient as KeetaNetUserClient } from '@keetanetwork/keetanet-client';\nimport type { Decimal } from 'decimal.js';\n\nimport type { ServiceSearchCriteria } from '../../lib/resolver.js';\n\nexport type KeetaNetAccount = InstanceType<typeof KeetaNetLib.Account>;\nexport type KeetaNetToken = InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN>>;\nexport type KeetaNetTokenPublicKeyString = ReturnType<InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN>>['publicKeyString']['get']>;\n\nexport type ConversionInput = {\n\t/**\n\t * The currency code to convert from (i.e., what the user has).\n\t */\n\tfrom: ServiceSearchCriteria<'fx'>['inputCurrencyCode'] | KeetaNetToken;\n\t/**\n\t * The currency code to convert to (i.e., what the user wants).\n\t */\n\tto: ServiceSearchCriteria<'fx'>['outputCurrencyCode'] | KeetaNetToken;\n\t/**\n\t * The amount to convert. This is a string or Decimal representing the\n\t * amount in the currency specified by either `from` or `to`, as\n\t * specified by the `affinity` property.\n\t */\n\tamount: string | number | Decimal;\n\t/**\n\t * Indicates whether the amount specified is in terms of the `from`\n\t * currency (i.e., the user has this much) or the `to` currency\n\t * (i.e., the user wants this much).\n\t */\n\taffinity: 'from' | 'to';\n};\n\nexport type ConversionInputCanonical = {\n\t[k in keyof ConversionInput]: k extends 'amount' ? string : k extends 'from' ? KeetaNetTokenPublicKeyString : k extends 'to' ? KeetaNetTokenPublicKeyString : ConversionInput[k];\n};\n\nexport type KeetaFXAnchorClientCreateExchangeRequest = {\n\tquote: KeetaFXAnchorQuote;\n\tblock: InstanceType<typeof KeetaNetLib.Block>;\n};\n\nexport type KeetaFXAnchorClientGetExchangeStatusRequest = {\n\texchangeID: string\n};\n\nexport type KeetaFXAnchorEstimate = {\n\t/**\n\t * Conversion request that was provided\n\t */\n\trequest: ConversionInputCanonical;\n\n\t/**\n\t * Amount after the conversion as specified by either `from` or `to`, as specified by the `affinity` property in the request.\n\t */\n\tconvertedAmount: string;\n\n\t/**\n\t * The expected cost of the fx request, in the form of a\n\t * token and a range of minimum and maximum expected costs\n\t */\n\texpectedCost: {\n\t\tmin: string;\n\t\tmax: string;\n\t\ttoken: KeetaNetTokenPublicKeyString;\n\t};\n};\n\nexport type KeetaFXAnchorEstimateResponse = ({\n\tok: true;\n\testimate: KeetaFXAnchorEstimate;\n} | {\n\tok: false;\n\terror: string;\n});\n\nexport type KeetaFXAnchorQuote = {\n\t/**\n\t * Conversion request that was provided\n\t */\n\trequest: ConversionInputCanonical;\n\n\t/**\n\t * The public key of the liquidity provider account\n\t */\n\taccount: string;\n\n\t/**\n\t * Amount after the conversion as specified by either `from` or `to`, as specified by the `affinity` property in the request.\n\t */\n\n\tconvertedAmount: string;\n\n\t/**\n\t * The cost of the fx request, in the form of a\n\t * token and amount that should be included with the swap\n\t */\n\tcost: {\n\t\tamount: string;\n\t\ttoken: KeetaNetTokenPublicKeyString;\n\t};\n\n\t/**\n\t * Signature information to verify the quote\n\t */\n\tsigned: {\n\t\tnonce: string;\n\t\t/* Date and time of the request in ISO 8601 format */\n\t\ttimestamp: string;\n\t\t/* Signature of the account public key and the nonce as an ASN.1 Sequence, Base64 DER */\n\t\tsignature: string;\n\t}\n};\n\nexport type KeetaFXAnchorQuoteResponse = ({\n\tok: true;\n\tquote: KeetaFXAnchorQuote\n} | {\n\tok: false;\n\terror: string;\n});\n\nexport type KeetaFXAnchorExchange = {\n\t/**\n\t * ID used to identify the conversion request\n\t */\n\texchangeID: string\n}\n\nexport type KeetaFXAnchorExchangeResponse = KeetaFXAnchorExchange &\n({\n\tok: true;\n} | {\n\tok: false;\n\terror: string;\n});\n\n/**\n * @deprecated Use the Node UserClient methods in the future instead of this function\n */\nexport async function createSwapRequest(userClient: KeetaNetUserClient, from: { account: KeetaNetAccount, token: KeetaNetToken, amount: bigint }, to: { account: KeetaNetAccount, token: KeetaNetToken, amount: bigint }): Promise<InstanceType<typeof KeetaNetLib.Block>> {\n\tconst builder = userClient.initBuilder();\n\tbuilder.send(to.account, from.amount, from.token);\n\tbuilder.receive(to.account, to.amount, to.token, true)\n\tconst blocks = await builder.computeBlocks();\n\n\tif (blocks.blocks.length !== 1) {\n\t\tthrow(new Error('Compute Swap Request Generated more than 1 block'));\n\t}\n\n\tconst block = blocks.blocks[0];\n\tif (block === undefined) {\n\t\tthrow(new Error('Swap Block is undefined'));\n\t}\n\n\treturn(block);\n}\n\n/**\n * @deprecated Use the Node UserClient methods in the future instead of this function\n */\nexport async function acceptSwapRequest(userClient: KeetaNetUserClient, request: InstanceType<typeof KeetaNetLib.Block>, expected: { token?: KeetaNetToken, amount?: bigint }): Promise<InstanceType<typeof KeetaNetLib.Block>[]> {\n\tconst builder = userClient.initBuilder();\n\n\tconst sendOperation = request.operations.find(({ type }) => KeetaNetLib.Block.OperationType.SEND === type);\n\tif (!sendOperation || sendOperation.type !== KeetaNetLib.Block.OperationType.SEND) {\n\t\tthrow(new Error('Swap Request is missing send'));\n\t}\n\tif (!sendOperation.to.comparePublicKey(userClient.account)) {\n\t\tthrow(new Error(`Swap Request send account does not match`));\n\t}\n\tif (expected.token !== undefined && !sendOperation.token.comparePublicKey(expected.token)) {\n\t\tthrow(new Error('Swap Request send token does not match expected'))\n\t}\n\tif (expected.amount !== undefined && sendOperation.amount !== expected.amount) {\n\t\tthrow(new Error(`Swap Request send amount ${sendOperation.amount} does not match expected amount ${expected.amount}`))\n\t}\n\n\tconst receiveOperation = request.operations.find(({ type }) => KeetaNetLib.Block.OperationType.RECEIVE === type);\n\tif (!receiveOperation || receiveOperation.type !== KeetaNetLib.Block.OperationType.RECEIVE) {\n\t\tthrow(new Error(\"Swap Request is missing receive operation\"));\n\t}\n\tbuilder.send(request.account, receiveOperation.amount, receiveOperation.token);\n\n\tconst blocks = await builder.computeBlocks();\n\treturn([...blocks.blocks, request]);\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as KeetaAnchorHTTPServer from '../../lib/http-server.js';
|
|
2
|
+
import KeetaNet from '@keetanetwork/keetanet-client';
|
|
3
|
+
import type { ConversionInputCanonical, KeetaFXAnchorQuote } from './common.ts';
|
|
4
|
+
import * as Signing from '../../lib/utils/signing.js';
|
|
5
|
+
export interface KeetaAnchorFXServerConfig extends KeetaAnchorHTTPServer.KeetaAnchorHTTPServerConfig {
|
|
6
|
+
/**
|
|
7
|
+
* The data to use for the index page (optional)
|
|
8
|
+
*/
|
|
9
|
+
homepage?: string | (() => Promise<string> | string);
|
|
10
|
+
/**
|
|
11
|
+
* The account to use for performing swaps for a given pair
|
|
12
|
+
*
|
|
13
|
+
* This may be either a function or a KeetaNet Account instance.
|
|
14
|
+
*/
|
|
15
|
+
account: InstanceType<typeof KeetaNet.lib.Account> | ((request: ConversionInputCanonical) => Promise<InstanceType<typeof KeetaNet.lib.Account>> | InstanceType<typeof KeetaNet.lib.Account>);
|
|
16
|
+
/**
|
|
17
|
+
* Account which can be used to sign transactions
|
|
18
|
+
* for the account above (if not supplied the
|
|
19
|
+
* account will be used).
|
|
20
|
+
*
|
|
21
|
+
* This may be either a function or a KeetaNet Account instance.
|
|
22
|
+
*/
|
|
23
|
+
signer?: InstanceType<typeof KeetaNet.lib.Account> | ((request: ConversionInputCanonical) => Promise<InstanceType<typeof KeetaNet.lib.Account>> | InstanceType<typeof KeetaNet.lib.Account>);
|
|
24
|
+
/**
|
|
25
|
+
* Account which performs the signing and validation of quotes
|
|
26
|
+
*/
|
|
27
|
+
quoteSigner: Signing.SignableAccount;
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for FX handling
|
|
30
|
+
*/
|
|
31
|
+
fx: {
|
|
32
|
+
/**
|
|
33
|
+
* Handle the conversion request of one token to another
|
|
34
|
+
*
|
|
35
|
+
* This is used to handle quotes and estimates
|
|
36
|
+
*/
|
|
37
|
+
getConversionRateAndFee: (request: ConversionInputCanonical) => Promise<Omit<KeetaFXAnchorQuote, 'request' | 'signed'>>;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The network client to use for submitting blocks
|
|
41
|
+
*/
|
|
42
|
+
client: {
|
|
43
|
+
client: KeetaNet.Client;
|
|
44
|
+
network: bigint;
|
|
45
|
+
networkAlias: typeof KeetaNet.Client.Config.networksArray[number];
|
|
46
|
+
} | KeetaNet.UserClient;
|
|
47
|
+
}
|
|
48
|
+
export declare class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAnchorHTTPServer<KeetaAnchorFXServerConfig> implements Required<KeetaAnchorFXServerConfig> {
|
|
49
|
+
readonly homepage: NonNullable<KeetaAnchorFXServerConfig['homepage']>;
|
|
50
|
+
readonly client: KeetaAnchorFXServerConfig['client'];
|
|
51
|
+
readonly account: KeetaAnchorFXServerConfig['account'];
|
|
52
|
+
readonly signer: NonNullable<KeetaAnchorFXServerConfig['signer']>;
|
|
53
|
+
readonly quoteSigner: KeetaAnchorFXServerConfig['quoteSigner'];
|
|
54
|
+
readonly fx: KeetaAnchorFXServerConfig['fx'];
|
|
55
|
+
constructor(config: KeetaAnchorFXServerConfig);
|
|
56
|
+
protected initRoutes(config: KeetaAnchorFXServerConfig): Promise<KeetaAnchorHTTPServer.Routes>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/services/fx/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,qBAAqB,MAAM,0BAA0B,CAAC;AAClE,OAAO,QAAQ,MAAM,+BAA+B,CAAC;AAKrD,OAAO,KAAK,EACX,wBAAwB,EAGxB,kBAAkB,EAElB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAC;AAMtD,MAAM,WAAW,yBAA0B,SAAQ,qBAAqB,CAAC,2BAA2B;IACnG;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;IAErD;;;;OAIG;IACH,OAAO,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,YAAY,CAAC,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7L;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,YAAY,CAAC,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAE7L;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC,eAAe,CAAC;IAErC;;OAEG;IACH,EAAE,EAAE;QACH;;;;WAIG;QACH,uBAAuB,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAE,CAAC,CAAC;KACzH,CAAC;IAEF;;OAEG;IACH,MAAM,EAAE;QAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,QAAQ,CAAC,UAAU,CAAC;CAC9I;AA6DD,qBAAa,0BAA2B,SAAQ,qBAAqB,CAAC,wBAAwB,CAAC,yBAAyB,CAAE,YAAW,QAAQ,CAAC,yBAAyB,CAAC;IACvK,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,yBAAyB,CAAC,UAAU,CAAC,CAAC,CAAC;IACtE,QAAQ,CAAC,MAAM,EAAE,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IACvD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClE,QAAQ,CAAC,WAAW,EAAE,yBAAyB,CAAC,aAAa,CAAC,CAAC;IAC/D,QAAQ,CAAC,EAAE,EAAE,yBAAyB,CAAC,IAAI,CAAC,CAAC;gBAEjC,MAAM,EAAE,yBAAyB;cAW7B,UAAU,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,qBAAqB,CAAC,MAAM,CAAC;CAwKpG"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import * as __typia_transform__assertGuard from "typia/lib/internal/_assertGuard.js";
|
|
2
|
+
import * as KeetaAnchorHTTPServer from '../../lib/http-server.js';
|
|
3
|
+
import KeetaNet from '@keetanetwork/keetanet-client';
|
|
4
|
+
import { createAssert } from 'typia';
|
|
5
|
+
import { KeetaAnchorUserError } from '../../lib/error.js';
|
|
6
|
+
import { acceptSwapRequest } from './common.js';
|
|
7
|
+
import * as Signing from '../../lib/utils/signing.js';
|
|
8
|
+
const assertConversionInputCanonical = (() => { const _io0 = 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 _ao0 = (input, _path, _exceptionable = true) => ("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)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
9
|
+
method: "createAssert",
|
|
10
|
+
path: _path + ".from",
|
|
11
|
+
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}`)",
|
|
12
|
+
value: input.from
|
|
13
|
+
}, _errorFactory)) && ("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)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
14
|
+
method: "createAssert",
|
|
15
|
+
path: _path + ".to",
|
|
16
|
+
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}`)",
|
|
17
|
+
value: input.to
|
|
18
|
+
}, _errorFactory)) && ("string" === typeof input.amount || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
19
|
+
method: "createAssert",
|
|
20
|
+
path: _path + ".amount",
|
|
21
|
+
expected: "string",
|
|
22
|
+
value: input.amount
|
|
23
|
+
}, _errorFactory)) && ("from" === input.affinity || "to" === input.affinity || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
24
|
+
method: "createAssert",
|
|
25
|
+
path: _path + ".affinity",
|
|
26
|
+
expected: "(\"from\" | \"to\")",
|
|
27
|
+
value: input.affinity
|
|
28
|
+
}, _errorFactory)); const __is = input => "object" === typeof input && null !== input && _io0(input); let _errorFactory; return (input, errorFactory) => {
|
|
29
|
+
if (false === __is(input)) {
|
|
30
|
+
_errorFactory = errorFactory;
|
|
31
|
+
((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || __typia_transform__assertGuard._assertGuard(true, {
|
|
32
|
+
method: "createAssert",
|
|
33
|
+
path: _path + "",
|
|
34
|
+
expected: "ConversionInputCanonical",
|
|
35
|
+
value: input
|
|
36
|
+
}, _errorFactory)) && _ao0(input, _path + "", true) || __typia_transform__assertGuard._assertGuard(true, {
|
|
37
|
+
method: "createAssert",
|
|
38
|
+
path: _path + "",
|
|
39
|
+
expected: "ConversionInputCanonical",
|
|
40
|
+
value: input
|
|
41
|
+
}, _errorFactory))(input, "$input", true);
|
|
42
|
+
}
|
|
43
|
+
return input;
|
|
44
|
+
}; })();
|
|
45
|
+
const assertConversionQuote = (() => { const _io0 = input => "object" === typeof input.request && null !== input.request && _io1(input.request) && "string" === typeof input.account && "string" === typeof input.convertedAmount && ("object" === typeof input.cost && null !== input.cost && _io2(input.cost)) && ("object" === typeof input.signed && null !== input.signed && _io3(input.signed)); 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.amount && ("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))); const _io3 = input => "string" === typeof input.nonce && "string" === typeof input.timestamp && "string" === typeof input.signature; const _ao0 = (input, _path, _exceptionable = true) => (("object" === typeof input.request && null !== input.request || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
46
|
+
method: "createAssert",
|
|
47
|
+
path: _path + ".request",
|
|
48
|
+
expected: "ConversionInputCanonical",
|
|
49
|
+
value: input.request
|
|
50
|
+
}, _errorFactory)) && _ao1(input.request, _path + ".request", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
51
|
+
method: "createAssert",
|
|
52
|
+
path: _path + ".request",
|
|
53
|
+
expected: "ConversionInputCanonical",
|
|
54
|
+
value: input.request
|
|
55
|
+
}, _errorFactory)) && ("string" === typeof input.account || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
56
|
+
method: "createAssert",
|
|
57
|
+
path: _path + ".account",
|
|
58
|
+
expected: "string",
|
|
59
|
+
value: input.account
|
|
60
|
+
}, _errorFactory)) && ("string" === typeof input.convertedAmount || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
61
|
+
method: "createAssert",
|
|
62
|
+
path: _path + ".convertedAmount",
|
|
63
|
+
expected: "string",
|
|
64
|
+
value: input.convertedAmount
|
|
65
|
+
}, _errorFactory)) && (("object" === typeof input.cost && null !== input.cost || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
66
|
+
method: "createAssert",
|
|
67
|
+
path: _path + ".cost",
|
|
68
|
+
expected: "__type",
|
|
69
|
+
value: input.cost
|
|
70
|
+
}, _errorFactory)) && _ao2(input.cost, _path + ".cost", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
71
|
+
method: "createAssert",
|
|
72
|
+
path: _path + ".cost",
|
|
73
|
+
expected: "__type",
|
|
74
|
+
value: input.cost
|
|
75
|
+
}, _errorFactory)) && (("object" === typeof input.signed && null !== input.signed || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
76
|
+
method: "createAssert",
|
|
77
|
+
path: _path + ".signed",
|
|
78
|
+
expected: "__type.o1",
|
|
79
|
+
value: input.signed
|
|
80
|
+
}, _errorFactory)) && _ao3(input.signed, _path + ".signed", true && _exceptionable) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
81
|
+
method: "createAssert",
|
|
82
|
+
path: _path + ".signed",
|
|
83
|
+
expected: "__type.o1",
|
|
84
|
+
value: input.signed
|
|
85
|
+
}, _errorFactory)); const _ao1 = (input, _path, _exceptionable = true) => ("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)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
86
|
+
method: "createAssert",
|
|
87
|
+
path: _path + ".from",
|
|
88
|
+
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}`)",
|
|
89
|
+
value: input.from
|
|
90
|
+
}, _errorFactory)) && ("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)) || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
91
|
+
method: "createAssert",
|
|
92
|
+
path: _path + ".to",
|
|
93
|
+
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}`)",
|
|
94
|
+
value: input.to
|
|
95
|
+
}, _errorFactory)) && ("string" === typeof input.amount || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
96
|
+
method: "createAssert",
|
|
97
|
+
path: _path + ".amount",
|
|
98
|
+
expected: "string",
|
|
99
|
+
value: input.amount
|
|
100
|
+
}, _errorFactory)) && ("from" === input.affinity || "to" === input.affinity || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
101
|
+
method: "createAssert",
|
|
102
|
+
path: _path + ".affinity",
|
|
103
|
+
expected: "(\"from\" | \"to\")",
|
|
104
|
+
value: input.affinity
|
|
105
|
+
}, _errorFactory)); const _ao2 = (input, _path, _exceptionable = true) => ("string" === typeof input.amount || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
106
|
+
method: "createAssert",
|
|
107
|
+
path: _path + ".amount",
|
|
108
|
+
expected: "string",
|
|
109
|
+
value: input.amount
|
|
110
|
+
}, _errorFactory)) && ("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, {
|
|
111
|
+
method: "createAssert",
|
|
112
|
+
path: _path + ".token",
|
|
113
|
+
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}`)",
|
|
114
|
+
value: input.token
|
|
115
|
+
}, _errorFactory)); const _ao3 = (input, _path, _exceptionable = true) => ("string" === typeof input.nonce || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
116
|
+
method: "createAssert",
|
|
117
|
+
path: _path + ".nonce",
|
|
118
|
+
expected: "string",
|
|
119
|
+
value: input.nonce
|
|
120
|
+
}, _errorFactory)) && ("string" === typeof input.timestamp || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
121
|
+
method: "createAssert",
|
|
122
|
+
path: _path + ".timestamp",
|
|
123
|
+
expected: "string",
|
|
124
|
+
value: input.timestamp
|
|
125
|
+
}, _errorFactory)) && ("string" === typeof input.signature || __typia_transform__assertGuard._assertGuard(_exceptionable, {
|
|
126
|
+
method: "createAssert",
|
|
127
|
+
path: _path + ".signature",
|
|
128
|
+
expected: "string",
|
|
129
|
+
value: input.signature
|
|
130
|
+
}, _errorFactory)); const __is = input => "object" === typeof input && null !== input && _io0(input); let _errorFactory; return (input, errorFactory) => {
|
|
131
|
+
if (false === __is(input)) {
|
|
132
|
+
_errorFactory = errorFactory;
|
|
133
|
+
((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || __typia_transform__assertGuard._assertGuard(true, {
|
|
134
|
+
method: "createAssert",
|
|
135
|
+
path: _path + "",
|
|
136
|
+
expected: "KeetaFXAnchorQuote",
|
|
137
|
+
value: input
|
|
138
|
+
}, _errorFactory)) && _ao0(input, _path + "", true) || __typia_transform__assertGuard._assertGuard(true, {
|
|
139
|
+
method: "createAssert",
|
|
140
|
+
path: _path + "",
|
|
141
|
+
expected: "KeetaFXAnchorQuote",
|
|
142
|
+
value: input
|
|
143
|
+
}, _errorFactory))(input, "$input", true);
|
|
144
|
+
}
|
|
145
|
+
return input;
|
|
146
|
+
}; })();
|
|
147
|
+
;
|
|
148
|
+
async function formatQuoteSignable(unsignedQuote) {
|
|
149
|
+
const retval = [
|
|
150
|
+
unsignedQuote.request.from,
|
|
151
|
+
unsignedQuote.request.to,
|
|
152
|
+
unsignedQuote.request.amount,
|
|
153
|
+
unsignedQuote.request.affinity,
|
|
154
|
+
unsignedQuote.account,
|
|
155
|
+
unsignedQuote.convertedAmount,
|
|
156
|
+
unsignedQuote.cost.token,
|
|
157
|
+
unsignedQuote.cost.amount
|
|
158
|
+
];
|
|
159
|
+
return (retval);
|
|
160
|
+
}
|
|
161
|
+
async function generateSignedQuote(signer, unsignedQuote) {
|
|
162
|
+
const signableQuote = await formatQuoteSignable(unsignedQuote);
|
|
163
|
+
const signed = await Signing.SignData(signer, signableQuote);
|
|
164
|
+
return ({
|
|
165
|
+
...unsignedQuote,
|
|
166
|
+
signed: signed
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
async function verifySignedData(signedBy, quote) {
|
|
170
|
+
const signableQuote = await formatQuoteSignable(quote);
|
|
171
|
+
return (await Signing.VerifySignedData(signedBy, signableQuote, quote.signed));
|
|
172
|
+
}
|
|
173
|
+
async function requestToAccounts(config, request) {
|
|
174
|
+
const account = KeetaNet.lib.Account.isInstance(config.account) ? config.account : await config.account(request);
|
|
175
|
+
let signer = null;
|
|
176
|
+
if (config.signer !== undefined) {
|
|
177
|
+
signer = (KeetaNet.lib.Account.isInstance(config.signer) ? config.signer : await config.signer(request)).assertAccount();
|
|
178
|
+
}
|
|
179
|
+
return ({
|
|
180
|
+
signer: signer ?? account.assertAccount(),
|
|
181
|
+
account: account.assertAccount()
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
export class KeetaNetFXAnchorHTTPServer extends KeetaAnchorHTTPServer.KeetaNetAnchorHTTPServer {
|
|
185
|
+
homepage;
|
|
186
|
+
client;
|
|
187
|
+
account;
|
|
188
|
+
signer;
|
|
189
|
+
quoteSigner;
|
|
190
|
+
fx;
|
|
191
|
+
constructor(config) {
|
|
192
|
+
super(config);
|
|
193
|
+
this.homepage = config.homepage ?? '';
|
|
194
|
+
this.client = config.client;
|
|
195
|
+
this.fx = config.fx;
|
|
196
|
+
this.account = config.account;
|
|
197
|
+
this.signer = config.signer ?? config.account;
|
|
198
|
+
this.quoteSigner = config.quoteSigner;
|
|
199
|
+
}
|
|
200
|
+
async initRoutes(config) {
|
|
201
|
+
const routes = {};
|
|
202
|
+
/**
|
|
203
|
+
* If a homepage is provided, setup the route for it
|
|
204
|
+
*/
|
|
205
|
+
if ('homepage' in config) {
|
|
206
|
+
routes['GET /'] = async function () {
|
|
207
|
+
let homepageData;
|
|
208
|
+
if (typeof config.homepage === 'string') {
|
|
209
|
+
homepageData = config.homepage;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
if (!config.homepage) {
|
|
213
|
+
throw (new Error('internal error: No homepage function provided'));
|
|
214
|
+
}
|
|
215
|
+
homepageData = await config.homepage();
|
|
216
|
+
}
|
|
217
|
+
return ({
|
|
218
|
+
output: homepageData,
|
|
219
|
+
contentType: 'text/html'
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Setup the request handler for an estimate request
|
|
225
|
+
*/
|
|
226
|
+
routes['POST /api/getEstimate'] = async function (_ignore_params, postData) {
|
|
227
|
+
if (!postData || typeof postData !== 'object') {
|
|
228
|
+
throw (new Error('No POST data provided'));
|
|
229
|
+
}
|
|
230
|
+
if (!('request' in postData)) {
|
|
231
|
+
throw (new Error('POST data missing request'));
|
|
232
|
+
}
|
|
233
|
+
const conversion = assertConversionInputCanonical(postData.request);
|
|
234
|
+
const rateAndFee = await config.fx.getConversionRateAndFee(conversion);
|
|
235
|
+
const estimateResponse = {
|
|
236
|
+
ok: true,
|
|
237
|
+
estimate: {
|
|
238
|
+
request: conversion,
|
|
239
|
+
convertedAmount: rateAndFee.convertedAmount,
|
|
240
|
+
expectedCost: {
|
|
241
|
+
min: rateAndFee.cost.amount,
|
|
242
|
+
max: rateAndFee.cost.amount,
|
|
243
|
+
token: rateAndFee.cost.token
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
return ({
|
|
248
|
+
output: JSON.stringify(estimateResponse)
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
routes['POST /api/getQuote'] = async function (_ignore_params, postData) {
|
|
252
|
+
if (!postData || typeof postData !== 'object') {
|
|
253
|
+
throw (new Error('No POST data provided'));
|
|
254
|
+
}
|
|
255
|
+
if (!('request' in postData)) {
|
|
256
|
+
throw (new Error('POST data missing request'));
|
|
257
|
+
}
|
|
258
|
+
const conversion = assertConversionInputCanonical(postData.request);
|
|
259
|
+
const rateAndFee = await config.fx.getConversionRateAndFee(conversion);
|
|
260
|
+
const unsignedQuote = {
|
|
261
|
+
request: conversion,
|
|
262
|
+
...rateAndFee
|
|
263
|
+
};
|
|
264
|
+
const signedQuote = await generateSignedQuote(config.quoteSigner, unsignedQuote);
|
|
265
|
+
const quoteResponse = {
|
|
266
|
+
ok: true,
|
|
267
|
+
quote: signedQuote
|
|
268
|
+
};
|
|
269
|
+
return ({
|
|
270
|
+
output: JSON.stringify(quoteResponse)
|
|
271
|
+
});
|
|
272
|
+
};
|
|
273
|
+
routes['POST /api/createExchange'] = async function (_ignore_params, postData) {
|
|
274
|
+
if (!postData || typeof postData !== 'object') {
|
|
275
|
+
throw (new Error('No POST data provided'));
|
|
276
|
+
}
|
|
277
|
+
if (!('request' in postData)) {
|
|
278
|
+
throw (new Error('POST data missing request'));
|
|
279
|
+
}
|
|
280
|
+
const request = postData.request;
|
|
281
|
+
if (!request || typeof request !== 'object') {
|
|
282
|
+
throw (new Error('Request is not an object'));
|
|
283
|
+
}
|
|
284
|
+
if (!('quote' in request)) {
|
|
285
|
+
throw (new Error('Quote is missing from request'));
|
|
286
|
+
}
|
|
287
|
+
if (!('block' in request) || typeof request.block !== 'string') {
|
|
288
|
+
throw (new Error('Block was not provided in exchange request'));
|
|
289
|
+
}
|
|
290
|
+
const quote = assertConversionQuote(request.quote);
|
|
291
|
+
const isValidQuote = await verifySignedData(config.quoteSigner, quote);
|
|
292
|
+
if (!isValidQuote) {
|
|
293
|
+
throw (new Error('Invalid quote signature'));
|
|
294
|
+
}
|
|
295
|
+
const block = new KeetaNet.lib.Block(request.block);
|
|
296
|
+
let userClient;
|
|
297
|
+
if (KeetaNet.UserClient.isInstance(config.client)) {
|
|
298
|
+
userClient = config.client;
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
const { account, signer } = await requestToAccounts(config, quote.request);
|
|
302
|
+
userClient = new KeetaNet.UserClient({
|
|
303
|
+
client: config.client.client,
|
|
304
|
+
network: config.client.network,
|
|
305
|
+
networkAlias: config.client.networkAlias,
|
|
306
|
+
account: account,
|
|
307
|
+
signer: signer
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
const expectedToken = KeetaNet.lib.Account.fromPublicKeyString(quote.request.from);
|
|
311
|
+
const expectedAmount = quote.request.affinity === 'from' ? quote.request.amount : quote.convertedAmount;
|
|
312
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
313
|
+
const swapBlocks = await acceptSwapRequest(userClient, block, { token: expectedToken, amount: BigInt(expectedAmount) });
|
|
314
|
+
const publishResult = await userClient.client.transmit(swapBlocks);
|
|
315
|
+
if (!publishResult.publish) {
|
|
316
|
+
throw (new Error('Exchange Publish Failed'));
|
|
317
|
+
}
|
|
318
|
+
const exchangeResponse = {
|
|
319
|
+
ok: true,
|
|
320
|
+
exchangeID: block.hash.toString()
|
|
321
|
+
};
|
|
322
|
+
return ({
|
|
323
|
+
output: JSON.stringify(exchangeResponse)
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
routes['GET /api/getExchangeStatus/:id'] = async function (params) {
|
|
327
|
+
if (params === undefined || params === null) {
|
|
328
|
+
throw (new KeetaAnchorUserError('Expected params'));
|
|
329
|
+
}
|
|
330
|
+
const exchangeID = params.get('id');
|
|
331
|
+
if (typeof exchangeID !== 'string') {
|
|
332
|
+
throw (new Error('Missing exchangeID in params'));
|
|
333
|
+
}
|
|
334
|
+
const blockLookup = await config.client.client.getVoteStaple(exchangeID);
|
|
335
|
+
if (blockLookup === null) {
|
|
336
|
+
throw (new Error('Block Not Found'));
|
|
337
|
+
}
|
|
338
|
+
const exchangeResponse = {
|
|
339
|
+
ok: true,
|
|
340
|
+
exchangeID: exchangeID
|
|
341
|
+
};
|
|
342
|
+
return ({
|
|
343
|
+
output: JSON.stringify(exchangeResponse)
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
return (routes);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=server.js.map
|