@silentswap/sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ import { EnglishMnemonic } from '@cosmjs/crypto';
2
+ import { FacilitatorAccount } from './facilitator-account.js';
3
+ import type { FacilitatorInstruction, FacilitatorPublicKey, FacilitatorReply } from './order.js';
4
+ import type { EncryptSecretKeyArgs } from './types/sdk.js';
5
+ import type { CoinTypeStr, IntStr } from './types/core.js';
6
+ export declare class HdFacilitatorGroup {
7
+ #private;
8
+ readonly accountIndex: number;
9
+ constructor(seed: Uint8Array, accountIndex: number);
10
+ /**
11
+ * Derives the facilitator account for the given BIP-44 coin type and index as in `m / purpose' / coin_type' / account' / change / address_index`
12
+ * @param coinType - SLIP-44 coin type (for the `coin_type` component of the BIP-44), '*' defaults to '0'
13
+ * @param addressIndex - `address_index` of the BIP-44
14
+ * @returns
15
+ */
16
+ account(coinType: number | CoinTypeStr, addressIndex: number | IntStr): Promise<FacilitatorAccount>;
17
+ exportPublicKeys(facilitatorCount: number, keySpecs: Omit<FacilitatorPublicKey, 'publicKeyBytes'>[]): Promise<FacilitatorPublicKey[][]>;
18
+ approveProxyAuthorizations(instructions: FacilitatorInstruction[], encryptArgs: EncryptSecretKeyArgs): Promise<FacilitatorReply[]>;
19
+ }
20
+ /**
21
+ * Exports a secret mnemonic seed phrase from the given entropy
22
+ * @param entropy - the secure entropy source to use
23
+ * @returns the English mnemonic seed phrase (24 words)
24
+ */
25
+ export declare function exportSecretMnemonicFromEntropy(entropy: Uint8Array): Promise<EnglishMnemonic>;
26
+ /**
27
+ * Creates a new hierarchical deterministic facilitator group of the given size from entropy, at some BIP-44 `account_index` offset
28
+ * @param entropy - the secure entropy source to use (should be derived deterministically so that accounts can be recovered)
29
+ * @param facilitatorCount - number of facilitators to create in this group, corresponds to number of order outputs
30
+ * @param orderIndex - increment for each new SilentSwap order; corresponds to the `account_index` in BIP-44
31
+ * @param password - optional password to use during mnemonic generation
32
+ * @returns
33
+ */
34
+ export declare function createHdFacilitatorGroupFromEntropy(entropy: Uint8Array, orderIndex: number | bigint, password?: string): Promise<HdFacilitatorGroup>;
@@ -0,0 +1,115 @@
1
+ import { keccak256 } from 'viem';
2
+ import { Bip39, Slip10, Slip10Curve, stringToPath } from '@cosmjs/crypto';
3
+ import { FacilitatorAccount } from './facilitator-account.js';
4
+ export class HdFacilitatorGroup {
5
+ accountIndex;
6
+ #seed;
7
+ constructor(seed, accountIndex) {
8
+ this.accountIndex = accountIndex;
9
+ // copy the bytes into a new section of memory so parent can zeroize original
10
+ this.#seed = seed.slice();
11
+ }
12
+ /**
13
+ * Derives the facilitator account for the given BIP-44 coin type and index as in `m / purpose' / coin_type' / account' / change / address_index`
14
+ * @param coinType - SLIP-44 coin type (for the `coin_type` component of the BIP-44), '*' defaults to '0'
15
+ * @param addressIndex - `address_index` of the BIP-44
16
+ * @returns
17
+ */
18
+ async account(coinType, addressIndex) {
19
+ // if global fallback type, use BTC (`0`)
20
+ if ('*' === coinType)
21
+ coinType = '0';
22
+ // derive BIP-32 nodem using BIP-44m for intended coin type at group's account index and given address index
23
+ const path = stringToPath(`m/44'/${coinType}'/${this.accountIndex}'/0/${addressIndex}`);
24
+ // export private key
25
+ const slip10Result = Slip10.derivePath(Slip10Curve.Secp256k1, this.#seed, path);
26
+ // create facilitator account
27
+ try {
28
+ return await new FacilitatorAccount(slip10Result.privkey);
29
+ }
30
+ // destroy the secret key
31
+ finally {
32
+ slip10Result.privkey.fill(0);
33
+ }
34
+ }
35
+ async exportPublicKeys(facilitatorCount, keySpecs) {
36
+ const exported = [];
37
+ for (let addrIndex = 0; addrIndex < facilitatorCount; addrIndex++) {
38
+ const pubKeys = [];
39
+ for (const spec of keySpecs) {
40
+ const account = await this.account(spec.coinType, addrIndex);
41
+ pubKeys.push(account.exportPublicKey(spec.coinType, spec.keyType));
42
+ }
43
+ exported.push(pubKeys);
44
+ }
45
+ return exported;
46
+ }
47
+ async approveProxyAuthorizations(instructions, encryptArgs) {
48
+ // each facilitator instruction
49
+ return await Promise.all(instructions.map(async (instruction, facilitatorIndex) => {
50
+ const accountsMap = {};
51
+ const exportedKeys = {};
52
+ // build mapping of public keys to accounts and exported private keys
53
+ for (const pubKey of instruction.publicKeys) {
54
+ const facilitatorPk = pubKey.publicKeyBytes;
55
+ // create facilitator account
56
+ const facilitator = accountsMap[facilitatorPk] = await this.account(pubKey.coinType, facilitatorIndex);
57
+ // encrypt its secret key and save to exports
58
+ exportedKeys[facilitatorPk] = await facilitator.encryptSecretKeyForProxy(encryptArgs);
59
+ }
60
+ // sign each authorization
61
+ const proxyAuthorizations = await Promise.all(instruction.proxyAuthorizations
62
+ .map(async (authorization, authIndex) => {
63
+ // ref facilitator's public key
64
+ const facilitatorPk = authorization.content.facilitator_pk;
65
+ // look up account
66
+ const account = accountsMap[facilitatorPk];
67
+ if (!account) {
68
+ throw Error(`Instruction at .facilitators[${facilitatorIndex}].proxyAuthorizations[${authIndex}] depends on public key ${facilitatorPk} which wasn't explicitly expressed in public keys map for this output`);
69
+ }
70
+ // sign proxy auth
71
+ return {
72
+ ...authorization,
73
+ signature: await account.signProxyAuthorization(authorization),
74
+ };
75
+ }));
76
+ return {
77
+ proxyAuthorizations,
78
+ exportedKeys,
79
+ };
80
+ }));
81
+ }
82
+ }
83
+ /**
84
+ * Exports a secret mnemonic seed phrase from the given entropy
85
+ * @param entropy - the secure entropy source to use
86
+ * @returns the English mnemonic seed phrase (24 words)
87
+ */
88
+ export async function exportSecretMnemonicFromEntropy(entropy) {
89
+ // get keccak256 hash of the entropy
90
+ const hash = keccak256(entropy, 'bytes');
91
+ // encode hash as mnemonic
92
+ return Bip39.encode(hash);
93
+ }
94
+ /**
95
+ * Creates a new hierarchical deterministic facilitator group of the given size from entropy, at some BIP-44 `account_index` offset
96
+ * @param entropy - the secure entropy source to use (should be derived deterministically so that accounts can be recovered)
97
+ * @param facilitatorCount - number of facilitators to create in this group, corresponds to number of order outputs
98
+ * @param orderIndex - increment for each new SilentSwap order; corresponds to the `account_index` in BIP-44
99
+ * @param password - optional password to use during mnemonic generation
100
+ * @returns
101
+ */
102
+ export async function createHdFacilitatorGroupFromEntropy(entropy, orderIndex, password) {
103
+ // generate mnemonic from entropy
104
+ const mnemonic = await exportSecretMnemonicFromEntropy(entropy);
105
+ // generate seed from mnemonic
106
+ const seed = await Bip39.mnemonicToSeed(mnemonic, password);
107
+ // create group from seed
108
+ try {
109
+ return new HdFacilitatorGroup(seed, Number(orderIndex));
110
+ }
111
+ // zeroize original seed bytes
112
+ finally {
113
+ seed.fill(0);
114
+ }
115
+ }
@@ -0,0 +1,7 @@
1
+ export type { SilentSwapClientConfig, SilentSwapClient, } from './client.js';
2
+ export type * from './types/api.js';
3
+ export type { EvmSigner } from './types/sdk.js';
4
+ export type * from './order.js';
5
+ export { createSilentSwapClient, } from './client.js';
6
+ export * from './constants.js';
7
+ export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { createSilentSwapClient, } from './client.js';
2
+ export * from './constants.js';
3
+ export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
@@ -0,0 +1,277 @@
1
+ import type { Hex } from 'viem';
2
+ import type { ExportedFacilitator, TypedDataDocument } from './types/sdk.js';
3
+ import type { Base64, Caip19, CoinTypeStr, IntStr } from './types/core.js';
4
+ import type { ProxyAuthInstruction, ProxyAuthReply } from './types/authorization.js';
5
+ import type { QuoteResponse } from './types/api.js';
6
+ import type { AbiParameter, ParseAbiParameters, TypedDataDomain } from 'abitype';
7
+ export declare enum DeliveryMethod {
8
+ SNIP = "SNIP"
9
+ }
10
+ export declare enum PrivacySetting {
11
+ LEAST_PRIVACY_FASTEST_SWAP = "LEAST_PRIVACY_FASTEST_SWAP",
12
+ WEAK = "WEAK",
13
+ FAIR = "FAIR",
14
+ STRONG = "STRONG",
15
+ EXTREME = "EXTREME"
16
+ }
17
+ export declare enum FacilitatorKeyType {
18
+ SECP256K1 = "SECP256K1",
19
+ ED25519 = "ED25519"
20
+ }
21
+ export type FacilitatorPublicKey = {
22
+ coinType: CoinTypeStr;
23
+ keyType: FacilitatorKeyType;
24
+ publicKeyBytes: Hex;
25
+ };
26
+ export declare const PublicKeyArgGroups: {
27
+ readonly GENERIC: readonly [{
28
+ readonly coinType: "*";
29
+ readonly keyType: FacilitatorKeyType.SECP256K1;
30
+ }, {
31
+ readonly coinType: "60";
32
+ readonly keyType: FacilitatorKeyType.SECP256K1;
33
+ }, {
34
+ readonly coinType: "118";
35
+ readonly keyType: FacilitatorKeyType.SECP256K1;
36
+ }, {
37
+ readonly coinType: "529";
38
+ readonly keyType: FacilitatorKeyType.SECP256K1;
39
+ }];
40
+ };
41
+ type Eip712DocumentParams = {
42
+ domainParams: readonly AbiParameter[];
43
+ customTypes: Record<string, readonly AbiParameter[]>;
44
+ primaryType: string;
45
+ domain: TypedDataDomain;
46
+ message: object;
47
+ };
48
+ export type Eip712Document<P extends Eip712DocumentParams = Eip712DocumentParams> = {
49
+ types: {
50
+ EIP712Domain?: P['domainParams'];
51
+ } & P['customTypes'];
52
+ primaryType: P['primaryType'];
53
+ domain: P['domain'];
54
+ message: P['message'];
55
+ };
56
+ export type Eip3009TypedData = Eip712Document<{
57
+ domainParams: ParseAbiParameters<'string name, string version, uint256 chainId, address verifyingContract'>;
58
+ customTypes: {
59
+ ReceiveWithAuthorization: ParseAbiParameters<'address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce'>;
60
+ };
61
+ primaryType: 'ReceiveWithAuthorization';
62
+ domain: {
63
+ name: 'USD Coin';
64
+ version: '2';
65
+ chainId: number;
66
+ verifyingContract: Hex;
67
+ };
68
+ message: {
69
+ from: Hex;
70
+ to: Hex;
71
+ value: IntStr;
72
+ validAfter: IntStr;
73
+ validBefore: IntStr;
74
+ nonce: Hex;
75
+ };
76
+ }>;
77
+ export type AuthorizationInstruction = {
78
+ id: Base64;
79
+ address: Hex;
80
+ } & (({
81
+ hash?: Hex;
82
+ } & ({
83
+ type: 'eip3009_deposit';
84
+ eip712: Eip3009TypedData;
85
+ })));
86
+ export type AuthorizationReply = AuthorizationInstruction & {
87
+ signature: Hex;
88
+ };
89
+ export type FacilitatorInstruction = {
90
+ publicKeys: FacilitatorPublicKey[];
91
+ proxyAuthorizations: ProxyAuthInstruction[];
92
+ };
93
+ export type FacilitatorReply = {
94
+ proxyAuthorizations: ProxyAuthReply[];
95
+ exportedKeys: Record<Hex, ExportedFacilitator>;
96
+ };
97
+ export type OrderOutputArg = {
98
+ /**
99
+ * Funds delivery method
100
+ */
101
+ method: DeliveryMethod;
102
+ /**
103
+ * CAIP-19 token ID
104
+ */
105
+ asset: Caip19;
106
+ /**
107
+ * Facilitator public keys
108
+ */
109
+ facilitatorPublicKeys: FacilitatorPublicKey[];
110
+ /**
111
+ * Recipient address
112
+ */
113
+ recipient: string;
114
+ /**
115
+ * Value
116
+ */
117
+ value: IntStr;
118
+ /**
119
+ * Extra optional settings
120
+ */
121
+ extra?: {
122
+ /**
123
+ * Swap settings
124
+ */
125
+ swap?: {
126
+ /**
127
+ * Slippage in basis points
128
+ */
129
+ slippageBps?: IntStr;
130
+ /**
131
+ * Minimum amount of output token to receive in base units
132
+ */
133
+ minimumAmount?: IntStr;
134
+ /**
135
+ * If present, performs a swap for exact amount out and sets the designated address as the refundee for overflow
136
+ */
137
+ exactAmountOutRefundee?: string;
138
+ };
139
+ };
140
+ };
141
+ export type OrderMetadata = {
142
+ notaryContract: {
143
+ chainId: 'secret-4';
144
+ contractAddress: `secret1${string}`;
145
+ encryptionPk33: Base64;
146
+ signerAddress: Hex;
147
+ sessionProof: Base64;
148
+ };
149
+ };
150
+ export type Quote = {
151
+ nonce: string;
152
+ signer: Hex;
153
+ privacy: PrivacySetting;
154
+ deposit: IntStr;
155
+ fee: IntStr;
156
+ outputs: Array<OrderOutputArg>;
157
+ metadata: OrderMetadata;
158
+ };
159
+ export type Order = {
160
+ orderId: string;
161
+ } & Quote;
162
+ export declare const EIP712_TYPES_ORDER: {
163
+ readonly EIP712Domain: readonly [{
164
+ readonly name: "name";
165
+ readonly type: "string";
166
+ }, {
167
+ readonly name: "version";
168
+ readonly type: "string";
169
+ }, {
170
+ readonly name: "chainId";
171
+ readonly type: "uint256";
172
+ }];
173
+ readonly Order: readonly [{
174
+ readonly name: "quoteId";
175
+ readonly type: "string";
176
+ }, {
177
+ readonly name: "quote";
178
+ readonly type: "Quote";
179
+ }];
180
+ readonly Quote: readonly [{
181
+ readonly name: "signer";
182
+ readonly type: "address";
183
+ }, {
184
+ readonly name: "nonce";
185
+ readonly type: "uint256";
186
+ }, {
187
+ readonly name: "privacy";
188
+ readonly type: "string";
189
+ }, {
190
+ readonly name: "deposit";
191
+ readonly type: "uint256";
192
+ }, {
193
+ readonly name: "fee";
194
+ readonly type: "uint256";
195
+ }, {
196
+ readonly name: "outputs";
197
+ readonly type: "Output[]";
198
+ }, {
199
+ readonly name: "metadata";
200
+ readonly type: "Metadata";
201
+ }];
202
+ readonly Output: readonly [{
203
+ readonly name: "method";
204
+ readonly type: "string";
205
+ }, {
206
+ readonly name: "asset";
207
+ readonly type: "string";
208
+ }, {
209
+ readonly name: "facilitatorPublicKeys";
210
+ readonly type: "Facilitator[]";
211
+ }, {
212
+ readonly name: "recipient";
213
+ readonly type: "string";
214
+ }, {
215
+ readonly name: "value";
216
+ readonly type: "uint256";
217
+ }, {
218
+ readonly name: "extra";
219
+ readonly type: "string";
220
+ }];
221
+ readonly Facilitator: readonly [{
222
+ readonly name: "coinType";
223
+ readonly type: "string";
224
+ }, {
225
+ readonly name: "keyType";
226
+ readonly type: "string";
227
+ }, {
228
+ readonly name: "publicKeyBytes";
229
+ readonly type: "bytes";
230
+ }];
231
+ readonly Metadata: readonly [{
232
+ readonly name: "notaryContract";
233
+ readonly type: "NotaryContract";
234
+ }];
235
+ readonly NotaryContract: readonly [{
236
+ readonly name: "chainId";
237
+ readonly type: "string";
238
+ }, {
239
+ readonly name: "contractAddress";
240
+ readonly type: "string";
241
+ }, {
242
+ readonly name: "encryptionPk33";
243
+ readonly type: "string";
244
+ }, {
245
+ readonly name: "signerAddress";
246
+ readonly type: "address";
247
+ }, {
248
+ readonly name: "sessionProof";
249
+ readonly type: "string";
250
+ }];
251
+ };
252
+ export declare const EIP712_TYPES_WALLET_GENERATION: {
253
+ readonly EIP712Domain: readonly [{
254
+ readonly name: "name";
255
+ readonly type: "string";
256
+ }, {
257
+ readonly name: "version";
258
+ readonly type: "string";
259
+ }, {
260
+ readonly name: "chainId";
261
+ readonly type: "uint256";
262
+ }];
263
+ readonly WalletGeneration: readonly [{
264
+ readonly name: "description";
265
+ readonly type: "string";
266
+ }, {
267
+ readonly name: "token";
268
+ readonly type: "string";
269
+ }];
270
+ };
271
+ export declare const EIP712_DOMAIN_ORDER_DEFAULT: {
272
+ readonly name: "SilentSwap v2";
273
+ readonly version: "1";
274
+ readonly chainId: 43114;
275
+ };
276
+ export declare function quoteResponseToEip712Document(quoteResponse: QuoteResponse): TypedDataDocument<typeof EIP712_DOMAIN_ORDER_DEFAULT>;
277
+ export {};
package/dist/order.js ADDED
@@ -0,0 +1,111 @@
1
+ export var DeliveryMethod;
2
+ (function (DeliveryMethod) {
3
+ DeliveryMethod["SNIP"] = "SNIP";
4
+ })(DeliveryMethod || (DeliveryMethod = {}));
5
+ export var PrivacySetting;
6
+ (function (PrivacySetting) {
7
+ PrivacySetting["LEAST_PRIVACY_FASTEST_SWAP"] = "LEAST_PRIVACY_FASTEST_SWAP";
8
+ PrivacySetting["WEAK"] = "WEAK";
9
+ PrivacySetting["FAIR"] = "FAIR";
10
+ PrivacySetting["STRONG"] = "STRONG";
11
+ PrivacySetting["EXTREME"] = "EXTREME";
12
+ })(PrivacySetting || (PrivacySetting = {}));
13
+ export var FacilitatorKeyType;
14
+ (function (FacilitatorKeyType) {
15
+ FacilitatorKeyType["SECP256K1"] = "SECP256K1";
16
+ FacilitatorKeyType["ED25519"] = "ED25519";
17
+ })(FacilitatorKeyType || (FacilitatorKeyType = {}));
18
+ export const PublicKeyArgGroups = {
19
+ GENERIC: [
20
+ {
21
+ coinType: '*',
22
+ keyType: FacilitatorKeyType.SECP256K1,
23
+ },
24
+ {
25
+ coinType: '60',
26
+ keyType: FacilitatorKeyType.SECP256K1,
27
+ },
28
+ {
29
+ coinType: '118',
30
+ keyType: FacilitatorKeyType.SECP256K1,
31
+ },
32
+ // {
33
+ // coinType: '501',
34
+ // keyType: FacilitatorKeyType.ED25519,
35
+ // },
36
+ {
37
+ coinType: '529',
38
+ keyType: FacilitatorKeyType.SECP256K1,
39
+ },
40
+ ],
41
+ };
42
+ export const EIP712_TYPES_ORDER = {
43
+ EIP712Domain: [
44
+ { name: 'name', type: 'string' },
45
+ { name: 'version', type: 'string' },
46
+ { name: 'chainId', type: 'uint256' },
47
+ ],
48
+ Order: [
49
+ { name: 'quoteId', type: 'string' },
50
+ { name: 'quote', type: 'Quote' },
51
+ ],
52
+ Quote: [
53
+ { name: 'signer', type: 'address' },
54
+ { name: 'nonce', type: 'uint256' },
55
+ { name: 'privacy', type: 'string' },
56
+ { name: 'deposit', type: 'uint256' },
57
+ { name: 'fee', type: 'uint256' },
58
+ { name: 'outputs', type: 'Output[]' },
59
+ { name: 'metadata', type: 'Metadata' },
60
+ ],
61
+ Output: [
62
+ { name: 'method', type: 'string' },
63
+ { name: 'asset', type: 'string' },
64
+ { name: 'facilitatorPublicKeys', type: 'Facilitator[]' },
65
+ { name: 'recipient', type: 'string' },
66
+ { name: 'value', type: 'uint256' },
67
+ { name: 'extra', type: 'string' },
68
+ ],
69
+ Facilitator: [
70
+ { name: 'coinType', type: 'string' },
71
+ { name: 'keyType', type: 'string' },
72
+ { name: 'publicKeyBytes', type: 'bytes' },
73
+ ],
74
+ Metadata: [
75
+ { name: 'notaryContract', type: 'NotaryContract' },
76
+ ],
77
+ NotaryContract: [
78
+ { name: 'chainId', type: 'string' },
79
+ { name: 'contractAddress', type: 'string' },
80
+ { name: 'encryptionPk33', type: 'string' },
81
+ { name: 'signerAddress', type: 'address' },
82
+ { name: 'sessionProof', type: 'string' },
83
+ ],
84
+ };
85
+ export const EIP712_TYPES_WALLET_GENERATION = {
86
+ EIP712Domain: [
87
+ { name: 'name', type: 'string' },
88
+ { name: 'version', type: 'string' },
89
+ { name: 'chainId', type: 'uint256' },
90
+ ],
91
+ WalletGeneration: [
92
+ { name: 'description', type: 'string' },
93
+ { name: 'token', type: 'string' },
94
+ ],
95
+ };
96
+ export const EIP712_DOMAIN_ORDER_DEFAULT = {
97
+ name: 'SilentSwap v2',
98
+ version: '1',
99
+ chainId: 43114,
100
+ };
101
+ export function quoteResponseToEip712Document(quoteResponse) {
102
+ return {
103
+ domain: EIP712_DOMAIN_ORDER_DEFAULT,
104
+ types: EIP712_TYPES_ORDER,
105
+ primaryType: 'Order',
106
+ message: {
107
+ quoteId: quoteResponse.quoteId,
108
+ quote: quoteResponse.quote,
109
+ },
110
+ };
111
+ }