@0xsequence/wallet-wdk 0.0.0-20250520201059

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.
Files changed (173) hide show
  1. package/.env.test +3 -0
  2. package/.turbo/turbo-build.log +5 -0
  3. package/CHANGELOG.md +11 -0
  4. package/LICENSE +202 -0
  5. package/dist/dbs/auth-commitments.d.ts +17 -0
  6. package/dist/dbs/auth-commitments.d.ts.map +1 -0
  7. package/dist/dbs/auth-commitments.js +13 -0
  8. package/dist/dbs/auth-keys.d.ts +19 -0
  9. package/dist/dbs/auth-keys.d.ts.map +1 -0
  10. package/dist/dbs/auth-keys.js +67 -0
  11. package/dist/dbs/generic.d.ts +33 -0
  12. package/dist/dbs/generic.d.ts.map +1 -0
  13. package/dist/dbs/generic.js +170 -0
  14. package/dist/dbs/index.d.ts +12 -0
  15. package/dist/dbs/index.d.ts.map +1 -0
  16. package/dist/dbs/index.js +8 -0
  17. package/dist/dbs/messages.d.ts +6 -0
  18. package/dist/dbs/messages.d.ts.map +1 -0
  19. package/dist/dbs/messages.js +13 -0
  20. package/dist/dbs/recovery.d.ts +6 -0
  21. package/dist/dbs/recovery.d.ts.map +1 -0
  22. package/dist/dbs/recovery.js +13 -0
  23. package/dist/dbs/signatures.d.ts +6 -0
  24. package/dist/dbs/signatures.d.ts.map +1 -0
  25. package/dist/dbs/signatures.js +13 -0
  26. package/dist/dbs/transactions.d.ts +6 -0
  27. package/dist/dbs/transactions.d.ts.map +1 -0
  28. package/dist/dbs/transactions.js +13 -0
  29. package/dist/dbs/wallets.d.ts +6 -0
  30. package/dist/dbs/wallets.d.ts.map +1 -0
  31. package/dist/dbs/wallets.js +13 -0
  32. package/dist/identity/signer.d.ts +17 -0
  33. package/dist/identity/signer.d.ts.map +1 -0
  34. package/dist/identity/signer.js +58 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +2 -0
  38. package/dist/sequence/cron.d.ts +19 -0
  39. package/dist/sequence/cron.d.ts.map +1 -0
  40. package/dist/sequence/cron.js +118 -0
  41. package/dist/sequence/devices.d.ts +14 -0
  42. package/dist/sequence/devices.d.ts.map +1 -0
  43. package/dist/sequence/devices.js +43 -0
  44. package/dist/sequence/handlers/authcode-pkce.d.ts +14 -0
  45. package/dist/sequence/handlers/authcode-pkce.d.ts.map +1 -0
  46. package/dist/sequence/handlers/authcode-pkce.js +48 -0
  47. package/dist/sequence/handlers/authcode.d.ts +25 -0
  48. package/dist/sequence/handlers/authcode.d.ts.map +1 -0
  49. package/dist/sequence/handlers/authcode.js +91 -0
  50. package/dist/sequence/handlers/devices.d.ts +14 -0
  51. package/dist/sequence/handlers/devices.d.ts.map +1 -0
  52. package/dist/sequence/handlers/devices.js +39 -0
  53. package/dist/sequence/handlers/handler.d.ts +8 -0
  54. package/dist/sequence/handlers/handler.d.ts.map +1 -0
  55. package/dist/sequence/handlers/handler.js +1 -0
  56. package/dist/sequence/handlers/identity.d.ts +21 -0
  57. package/dist/sequence/handlers/identity.d.ts.map +1 -0
  58. package/dist/sequence/handlers/identity.js +86 -0
  59. package/dist/sequence/handlers/index.d.ts +7 -0
  60. package/dist/sequence/handlers/index.d.ts.map +1 -0
  61. package/dist/sequence/handlers/index.js +5 -0
  62. package/dist/sequence/handlers/mnemonic.d.ts +19 -0
  63. package/dist/sequence/handlers/mnemonic.d.ts.map +1 -0
  64. package/dist/sequence/handlers/mnemonic.js +67 -0
  65. package/dist/sequence/handlers/otp.d.ts +20 -0
  66. package/dist/sequence/handlers/otp.d.ts.map +1 -0
  67. package/dist/sequence/handlers/otp.js +83 -0
  68. package/dist/sequence/handlers/passkeys.d.ts +17 -0
  69. package/dist/sequence/handlers/passkeys.d.ts.map +1 -0
  70. package/dist/sequence/handlers/passkeys.js +63 -0
  71. package/dist/sequence/handlers/recovery.d.ts +15 -0
  72. package/dist/sequence/handlers/recovery.d.ts.map +1 -0
  73. package/dist/sequence/handlers/recovery.js +72 -0
  74. package/dist/sequence/index.d.ts +12 -0
  75. package/dist/sequence/index.d.ts.map +1 -0
  76. package/dist/sequence/index.js +9 -0
  77. package/dist/sequence/logger.d.ts +7 -0
  78. package/dist/sequence/logger.d.ts.map +1 -0
  79. package/dist/sequence/logger.js +11 -0
  80. package/dist/sequence/manager.d.ts +287 -0
  81. package/dist/sequence/manager.d.ts.map +1 -0
  82. package/dist/sequence/manager.js +356 -0
  83. package/dist/sequence/messages.d.ts +18 -0
  84. package/dist/sequence/messages.d.ts.map +1 -0
  85. package/dist/sequence/messages.js +115 -0
  86. package/dist/sequence/recovery.d.ts +30 -0
  87. package/dist/sequence/recovery.d.ts.map +1 -0
  88. package/dist/sequence/recovery.js +314 -0
  89. package/dist/sequence/sessions.d.ts +26 -0
  90. package/dist/sequence/sessions.d.ts.map +1 -0
  91. package/dist/sequence/sessions.js +169 -0
  92. package/dist/sequence/signatures.d.ts +21 -0
  93. package/dist/sequence/signatures.d.ts.map +1 -0
  94. package/dist/sequence/signatures.js +192 -0
  95. package/dist/sequence/signers.d.ts +14 -0
  96. package/dist/sequence/signers.d.ts.map +1 -0
  97. package/dist/sequence/signers.js +74 -0
  98. package/dist/sequence/transactions.d.ts +26 -0
  99. package/dist/sequence/transactions.d.ts.map +1 -0
  100. package/dist/sequence/transactions.js +201 -0
  101. package/dist/sequence/types/index.d.ts +9 -0
  102. package/dist/sequence/types/index.d.ts.map +1 -0
  103. package/dist/sequence/types/index.js +2 -0
  104. package/dist/sequence/types/message-request.d.ts +23 -0
  105. package/dist/sequence/types/message-request.d.ts.map +1 -0
  106. package/dist/sequence/types/message-request.js +1 -0
  107. package/dist/sequence/types/recovery.d.ts +15 -0
  108. package/dist/sequence/types/recovery.d.ts.map +1 -0
  109. package/dist/sequence/types/recovery.js +1 -0
  110. package/dist/sequence/types/signature-request.d.ts +76 -0
  111. package/dist/sequence/types/signature-request.d.ts.map +1 -0
  112. package/dist/sequence/types/signature-request.js +11 -0
  113. package/dist/sequence/types/signer.d.ts +28 -0
  114. package/dist/sequence/types/signer.d.ts.map +1 -0
  115. package/dist/sequence/types/signer.js +10 -0
  116. package/dist/sequence/types/transaction-request.d.ts +41 -0
  117. package/dist/sequence/types/transaction-request.d.ts.map +1 -0
  118. package/dist/sequence/types/transaction-request.js +1 -0
  119. package/dist/sequence/types/wallet.d.ts +21 -0
  120. package/dist/sequence/types/wallet.d.ts.map +1 -0
  121. package/dist/sequence/types/wallet.js +1 -0
  122. package/dist/sequence/wallets.d.ts +121 -0
  123. package/dist/sequence/wallets.d.ts.map +1 -0
  124. package/dist/sequence/wallets.js +632 -0
  125. package/package.json +40 -0
  126. package/src/dbs/auth-commitments.ts +26 -0
  127. package/src/dbs/auth-keys.ts +85 -0
  128. package/src/dbs/generic.ts +194 -0
  129. package/src/dbs/index.ts +13 -0
  130. package/src/dbs/messages.ts +16 -0
  131. package/src/dbs/recovery.ts +15 -0
  132. package/src/dbs/signatures.ts +15 -0
  133. package/src/dbs/transactions.ts +16 -0
  134. package/src/dbs/wallets.ts +16 -0
  135. package/src/identity/signer.ts +78 -0
  136. package/src/index.ts +2 -0
  137. package/src/sequence/cron.ts +134 -0
  138. package/src/sequence/devices.ts +53 -0
  139. package/src/sequence/handlers/authcode-pkce.ts +70 -0
  140. package/src/sequence/handlers/authcode.ts +116 -0
  141. package/src/sequence/handlers/devices.ts +53 -0
  142. package/src/sequence/handlers/handler.ts +14 -0
  143. package/src/sequence/handlers/identity.ts +101 -0
  144. package/src/sequence/handlers/index.ts +6 -0
  145. package/src/sequence/handlers/mnemonic.ts +88 -0
  146. package/src/sequence/handlers/otp.ts +107 -0
  147. package/src/sequence/handlers/passkeys.ts +84 -0
  148. package/src/sequence/handlers/recovery.ts +88 -0
  149. package/src/sequence/index.ts +25 -0
  150. package/src/sequence/logger.ts +11 -0
  151. package/src/sequence/manager.ts +634 -0
  152. package/src/sequence/messages.ts +146 -0
  153. package/src/sequence/recovery.ts +429 -0
  154. package/src/sequence/sessions.ts +238 -0
  155. package/src/sequence/signatures.ts +263 -0
  156. package/src/sequence/signers.ts +88 -0
  157. package/src/sequence/transactions.ts +281 -0
  158. package/src/sequence/types/index.ts +27 -0
  159. package/src/sequence/types/message-request.ts +26 -0
  160. package/src/sequence/types/recovery.ts +15 -0
  161. package/src/sequence/types/signature-request.ts +89 -0
  162. package/src/sequence/types/signer.ts +32 -0
  163. package/src/sequence/types/transaction-request.ts +47 -0
  164. package/src/sequence/types/wallet.ts +24 -0
  165. package/src/sequence/wallets.ts +853 -0
  166. package/test/constants.ts +62 -0
  167. package/test/recovery.test.ts +211 -0
  168. package/test/sessions.test.ts +324 -0
  169. package/test/setup.ts +63 -0
  170. package/test/transactions.test.ts +464 -0
  171. package/test/wallets.test.ts +381 -0
  172. package/tsconfig.json +10 -0
  173. package/vitest.config.ts +11 -0
@@ -0,0 +1,21 @@
1
+ import { Envelope } from '@0xsequence/wallet-core';
2
+ import { Shared } from './manager.js';
3
+ import { Action, ActionToPayload, BaseSignatureRequest, SignatureRequest } from './types/signature-request.js';
4
+ export declare class Signatures {
5
+ private readonly shared;
6
+ constructor(shared: Shared);
7
+ initialize(): void;
8
+ private getBase;
9
+ list(): Promise<SignatureRequest[]>;
10
+ get(requestId: string): Promise<SignatureRequest>;
11
+ onSignatureRequestUpdate(requestId: string, cb: (requests: SignatureRequest) => void, onError?: (error: Error) => void, trigger?: boolean): () => void;
12
+ onSignatureRequestsUpdate(cb: (requests: BaseSignatureRequest[]) => void, trigger?: boolean): () => void;
13
+ complete(requestId: string): Promise<void>;
14
+ request<A extends Action>(envelope: Envelope.Envelope<ActionToPayload[A]>, action: A, options?: {
15
+ origin?: string;
16
+ }): Promise<string>;
17
+ addSignature(requestId: string, signature: Envelope.SapientSignature | Envelope.Signature): Promise<void>;
18
+ cancel(requestId: string): Promise<void>;
19
+ prune(): Promise<number>;
20
+ }
21
+ //# sourceMappingURL=signatures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signatures.d.ts","sourceRoot":"","sources":["../../src/sequence/signatures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAIlD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EACL,MAAM,EACN,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAIjB,MAAM,8BAA8B,CAAA;AAGrC,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAE3C,UAAU;YAUI,OAAO;IAQf,IAAI,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAInC,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyFvD,wBAAwB,CACtB,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,EACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EAChC,OAAO,CAAC,EAAE,OAAO;IA4BnB,yBAAyB,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,oBAAoB,EAAE,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO;IAYrF,QAAQ,CAAC,SAAS,EAAE,MAAM;IAuB1B,OAAO,CAAC,CAAC,SAAS,MAAM,EAC5B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAC/C,MAAM,EAAE,CAAC,EACT,OAAO,GAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAA;KACX,GACL,OAAO,CAAC,MAAM,CAAC;IAkCZ,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,gBAAgB,GAAG,QAAQ,CAAC,SAAS;IAQzF,MAAM,CAAC,SAAS,EAAE,MAAM;IAUxB,KAAK;CAOZ"}
@@ -0,0 +1,192 @@
1
+ import { Envelope } from '@0xsequence/wallet-core';
2
+ import { Config, Payload } from '@0xsequence/wallet-primitives';
3
+ import { Address, Hex } from 'ox';
4
+ import { v7 as uuidv7 } from 'uuid';
5
+ export class Signatures {
6
+ shared;
7
+ constructor(shared) {
8
+ this.shared = shared;
9
+ }
10
+ initialize() {
11
+ this.shared.modules.cron.registerJob('prune-signatures', 10 * 60 * 1000, async () => {
12
+ const prunedSignatures = await this.prune();
13
+ if (prunedSignatures > 0) {
14
+ this.shared.modules.logger.log(`Pruned ${prunedSignatures} signatures`);
15
+ }
16
+ });
17
+ this.shared.modules.logger.log('Signatures module initialized and job registered.');
18
+ }
19
+ async getBase(requestId) {
20
+ const request = await this.shared.databases.signatures.get(requestId);
21
+ if (!request) {
22
+ throw new Error(`Request not found for ${requestId}`);
23
+ }
24
+ return request;
25
+ }
26
+ async list() {
27
+ return this.shared.databases.signatures.list();
28
+ }
29
+ async get(requestId) {
30
+ const request = await this.getBase(requestId);
31
+ if (request.status !== 'pending' && request.scheduledPruning < Date.now()) {
32
+ await this.shared.databases.signatures.del(requestId);
33
+ throw new Error(`Request not found for ${requestId}`);
34
+ }
35
+ const signers = Config.getSigners(request.envelope.configuration.topology);
36
+ const signersAndKinds = await Promise.all([
37
+ ...signers.signers.map(async (signer) => {
38
+ const kind = await this.shared.modules.signers.kindOf(request.wallet, signer);
39
+ return {
40
+ address: signer,
41
+ imageHash: undefined,
42
+ kind,
43
+ };
44
+ }),
45
+ ...signers.sapientSigners.map(async (signer) => {
46
+ const kind = await this.shared.modules.signers.kindOf(request.wallet, signer.address, Hex.from(signer.imageHash));
47
+ return {
48
+ address: signer.address,
49
+ imageHash: signer.imageHash,
50
+ kind,
51
+ };
52
+ }),
53
+ ]);
54
+ const statuses = await Promise.all(signersAndKinds.map(async (sak) => {
55
+ const base = {
56
+ address: sak.address,
57
+ imageHash: sak.imageHash,
58
+ };
59
+ // We may have a signature for this signer already
60
+ const signed = request.envelope.signatures.some((sig) => {
61
+ if (Envelope.isSapientSignature(sig)) {
62
+ return Address.isEqual(sig.signature.address, sak.address) && sig.imageHash === sak.imageHash;
63
+ }
64
+ return Address.isEqual(sig.address, sak.address);
65
+ });
66
+ if (!sak.kind) {
67
+ const status = {
68
+ ...base,
69
+ handler: undefined,
70
+ reason: 'unknown-signer-kind',
71
+ status: 'unavailable',
72
+ };
73
+ return status;
74
+ }
75
+ const handler = this.shared.handlers.get(sak.kind);
76
+ if (signed) {
77
+ const status = {
78
+ ...base,
79
+ handler,
80
+ status: 'signed',
81
+ };
82
+ return status;
83
+ }
84
+ if (!handler) {
85
+ const status = {
86
+ ...base,
87
+ handler: undefined,
88
+ reason: 'no-handler',
89
+ status: 'unavailable',
90
+ };
91
+ return status;
92
+ }
93
+ return handler.status(sak.address, sak.imageHash, request);
94
+ }));
95
+ const signatureRequest = {
96
+ ...request,
97
+ ...Envelope.weightOf(request.envelope),
98
+ signers: statuses,
99
+ };
100
+ return signatureRequest;
101
+ }
102
+ onSignatureRequestUpdate(requestId, cb, onError, trigger) {
103
+ const undoDbListener = this.shared.databases.signatures.addListener(() => {
104
+ this.get(requestId)
105
+ .then((request) => cb(request))
106
+ .catch((error) => onError?.(error));
107
+ });
108
+ const undoHandlerListeners = Array.from(this.shared.handlers.values()).map((handler) => handler.onStatusChange(() => {
109
+ this.get(requestId)
110
+ .then((request) => cb(request))
111
+ .catch((error) => onError?.(error));
112
+ }));
113
+ if (trigger) {
114
+ this.get(requestId)
115
+ .then((request) => cb(request))
116
+ .catch((error) => onError?.(error));
117
+ }
118
+ return () => {
119
+ undoDbListener();
120
+ undoHandlerListeners.forEach((undoFn) => undoFn());
121
+ };
122
+ }
123
+ onSignatureRequestsUpdate(cb, trigger) {
124
+ const undo = this.shared.databases.signatures.addListener(() => {
125
+ this.list().then((l) => cb(l));
126
+ });
127
+ if (trigger) {
128
+ this.list().then((l) => cb(l));
129
+ }
130
+ return undo;
131
+ }
132
+ async complete(requestId) {
133
+ const request = await this.getBase(requestId);
134
+ if (request?.envelope.payload.type === 'config-update') {
135
+ // Clear pending config updates for the same wallet with a checkpoint equal or lower than the completed update
136
+ const pendingRequests = await this.shared.databases.signatures.list();
137
+ const pendingConfigUpdatesToClear = pendingRequests.filter((sig) => Address.isEqual(sig.wallet, request.wallet) &&
138
+ sig.envelope.payload.type === 'config-update' &&
139
+ sig.envelope.configuration.checkpoint <= request.envelope.configuration.checkpoint);
140
+ // This also deletes the requested id
141
+ await Promise.all(pendingConfigUpdatesToClear.map((sig) => this.shared.modules.signatures.cancel(sig.id)));
142
+ }
143
+ await this.shared.databases.signatures.set({
144
+ ...request,
145
+ status: 'completed',
146
+ scheduledPruning: Date.now() + this.shared.databases.pruningInterval,
147
+ });
148
+ }
149
+ async request(envelope, action, options = {}) {
150
+ // If the action is a config update, we need to remove all signature requests
151
+ // for the same wallet that also involve configuration updates
152
+ // as it may cause race conditions
153
+ // TODO: Eventually we should define a "delta configuration" signature request
154
+ if (Payload.isConfigUpdate(envelope.payload)) {
155
+ const pendingRequests = await this.shared.databases.signatures.list();
156
+ const pendingConfigUpdatesToClear = pendingRequests.filter((sig) => sig.wallet === envelope.wallet && Payload.isConfigUpdate(sig.envelope.payload));
157
+ console.warn('Deleting conflicting configuration updates for wallet', envelope.wallet, pendingConfigUpdatesToClear.map((pc) => pc.id));
158
+ await Promise.all(pendingConfigUpdatesToClear.map((sig) => this.shared.modules.signatures.cancel(sig.id)));
159
+ }
160
+ const id = uuidv7();
161
+ await this.shared.databases.signatures.set({
162
+ id,
163
+ wallet: envelope.wallet,
164
+ envelope: Envelope.toSigned(envelope),
165
+ origin: options.origin ?? 'unknown',
166
+ action,
167
+ createdAt: new Date().toISOString(),
168
+ status: 'pending',
169
+ });
170
+ return id;
171
+ }
172
+ async addSignature(requestId, signature) {
173
+ const request = await this.getBase(requestId);
174
+ Envelope.addSignature(request.envelope, signature);
175
+ await this.shared.databases.signatures.set(request);
176
+ }
177
+ async cancel(requestId) {
178
+ const request = await this.getBase(requestId);
179
+ await this.shared.databases.signatures.set({
180
+ ...request,
181
+ status: 'cancelled',
182
+ scheduledPruning: Date.now() + this.shared.databases.pruningInterval,
183
+ });
184
+ }
185
+ async prune() {
186
+ const now = Date.now();
187
+ const requests = await this.shared.databases.signatures.list();
188
+ const toPrune = requests.filter((req) => req.status !== 'pending' && req.scheduledPruning < now);
189
+ await Promise.all(toPrune.map((req) => this.shared.databases.signatures.del(req.id)));
190
+ return toPrune.length;
191
+ }
192
+ }
@@ -0,0 +1,14 @@
1
+ import { Address, Hex } from 'ox';
2
+ import { Shared } from './manager.js';
3
+ import { Kind, SignerWithKind, WitnessExtraSignerKind } from './types/signer.js';
4
+ export declare function isWitnessExtraSignerKind(extra: any): extra is WitnessExtraSignerKind;
5
+ export declare class Signers {
6
+ private readonly shared;
7
+ constructor(shared: Shared);
8
+ kindOf(wallet: Address.Address, address: Address.Address, imageHash?: Hex.Hex): Promise<Kind | undefined>;
9
+ resolveKinds(wallet: Address.Address, signers: (Address.Address | {
10
+ address: Address.Address;
11
+ imageHash: Hex.Hex;
12
+ })[]): Promise<SignerWithKind[]>;
13
+ }
14
+ //# sourceMappingURL=signers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signers.d.ts","sourceRoot":"","sources":["../../src/sequence/signers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,IAAI,EAAS,cAAc,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAEvF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,sBAAsB,CAEpF;AAeD,qBAAa,OAAO;IACN,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAErC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAuCzG,YAAY,CAChB,MAAM,EAAE,OAAO,CAAC,OAAO,EACvB,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAA;KAAE,CAAC,EAAE,GAC9E,OAAO,CAAC,cAAc,EAAE,CAAC;CAoB7B"}
@@ -0,0 +1,74 @@
1
+ import { Payload } from '@0xsequence/wallet-primitives';
2
+ import { Address, Hex } from 'ox';
3
+ import { Kinds } from './types/signer.js';
4
+ export function isWitnessExtraSignerKind(extra) {
5
+ return typeof extra === 'object' && extra !== null && 'signerKind' in extra;
6
+ }
7
+ function toKnownKind(kind) {
8
+ if (Object.values(Kinds).includes(kind)) {
9
+ return kind;
10
+ }
11
+ console.warn(`Unknown signer kind: ${kind}`);
12
+ return Kinds.Unknown;
13
+ }
14
+ // Signers is in charge to know (or figure out) the "kind" of each signer
15
+ // i.e., when a signature is requested, we only get address and imageHash (if sapient)
16
+ // this module takes care of figuring out the kind of signer (e.g., device, passkey, recovery, etc.)
17
+ export class Signers {
18
+ shared;
19
+ constructor(shared) {
20
+ this.shared = shared;
21
+ }
22
+ async kindOf(wallet, address, imageHash) {
23
+ // // The device may be among the local devices, in that case it is a local device
24
+ // // TODO: Maybe signers shouldn't be getting in the way of devices, it feels like a
25
+ // // different concern
26
+ // if (await this.devices.has(address)) {
27
+ // return Kinds.LocalDevice
28
+ // }
29
+ // Some signers are known by the configuration of the wallet development kit, specifically
30
+ // some of the sapient signers, who always share the same address
31
+ if (Address.isEqual(this.shared.sequence.extensions.recovery, address)) {
32
+ return Kinds.Recovery;
33
+ }
34
+ // We need to use the state provider (and witness) this will tell us the kind of signer
35
+ // NOTICE: This looks expensive, but this operation should be cached by the state provider
36
+ const witness = await (imageHash
37
+ ? this.shared.sequence.stateProvider.getWitnessForSapient(wallet, address, imageHash)
38
+ : this.shared.sequence.stateProvider.getWitnessFor(wallet, address));
39
+ if (!witness) {
40
+ return undefined;
41
+ }
42
+ // Parse the payload, it may have the kind of signer
43
+ if (!Payload.isMessage(witness.payload)) {
44
+ return undefined;
45
+ }
46
+ try {
47
+ const message = JSON.parse(Hex.toString(witness.payload.message));
48
+ if (isWitnessExtraSignerKind(message)) {
49
+ return toKnownKind(message.signerKind);
50
+ }
51
+ }
52
+ catch { }
53
+ return undefined;
54
+ }
55
+ async resolveKinds(wallet, signers) {
56
+ return Promise.all(signers.map(async (signer) => {
57
+ if (typeof signer === 'string') {
58
+ const kind = await this.kindOf(wallet, signer);
59
+ return {
60
+ address: signer,
61
+ kind,
62
+ };
63
+ }
64
+ else {
65
+ const kind = await this.kindOf(wallet, signer.address, signer.imageHash);
66
+ return {
67
+ address: signer.address,
68
+ imageHash: signer.imageHash,
69
+ kind,
70
+ };
71
+ }
72
+ }));
73
+ }
74
+ }
@@ -0,0 +1,26 @@
1
+ import { Payload } from '@0xsequence/wallet-primitives';
2
+ import { Address } from 'ox';
3
+ import { Shared } from './manager.js';
4
+ import { Transaction, TransactionRequest } from './types/transaction-request.js';
5
+ export declare class Transactions {
6
+ private readonly shared;
7
+ constructor(shared: Shared);
8
+ list(): Promise<Transaction[]>;
9
+ get(transactionId: string): Promise<Transaction>;
10
+ request(from: Address.Address, chainId: bigint, txs: TransactionRequest[], options?: {
11
+ skipDefineGas?: boolean;
12
+ source?: string;
13
+ noConfigUpdate?: boolean;
14
+ }): Promise<string>;
15
+ define(transactionId: string, changes?: {
16
+ nonce?: bigint;
17
+ space?: bigint;
18
+ calls?: Pick<Payload.Call, 'gasLimit'>[];
19
+ }): Promise<void>;
20
+ selectRelayer(transactionId: string, relayerOptionId: string): Promise<string>;
21
+ relay(transactionOrSignatureId: string): Promise<`0x${string}`>;
22
+ onTransactionsUpdate(cb: (transactions: Transaction[]) => void, trigger?: boolean): () => void;
23
+ onTransactionUpdate(transactionId: string, cb: (transaction: Transaction) => void, trigger?: boolean): () => void;
24
+ delete(transactionId: string): Promise<void>;
25
+ }
26
+ //# sourceMappingURL=transactions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../../src/sequence/transactions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAA;AAEvD,OAAO,EAAE,OAAO,EAA0B,MAAM,IAAI,CAAA;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAEL,WAAW,EAGX,kBAAkB,EACnB,MAAM,gCAAgC,CAAA;AAEvC,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAE9B,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI9B,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IASvD,OAAO,CACX,IAAI,EAAE,OAAO,CAAC,OAAO,EACrB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,kBAAkB,EAAE,EACzB,OAAO,CAAC,EAAE;QACR,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,cAAc,CAAC,EAAE,OAAO,CAAA;KACzB,GACA,OAAO,CAAC,MAAM,CAAC;IAuCZ,MAAM,CACV,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,KAAK,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAA;KACzC,GACA,OAAO,CAAC,IAAI,CAAC;IAuDV,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA2B9E,KAAK,CAAC,wBAAwB,EAAE,MAAM;IAiF5C,oBAAoB,CAAC,EAAE,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO;IAYjF,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO;IAY9F,MAAM,CAAC,aAAa,EAAE,MAAM;CASnC"}
@@ -0,0 +1,201 @@
1
+ import { Payload } from '@0xsequence/wallet-primitives';
2
+ import { Envelope, Wallet } from '@0xsequence/wallet-core';
3
+ import { Provider, RpcTransport } from 'ox';
4
+ import { v7 as uuidv7 } from 'uuid';
5
+ export class Transactions {
6
+ shared;
7
+ constructor(shared) {
8
+ this.shared = shared;
9
+ }
10
+ async list() {
11
+ return this.shared.databases.transactions.list();
12
+ }
13
+ async get(transactionId) {
14
+ const tx = await this.shared.databases.transactions.get(transactionId);
15
+ if (!tx) {
16
+ throw new Error(`Transaction ${transactionId} not found`);
17
+ }
18
+ return tx;
19
+ }
20
+ async request(from, chainId, txs, options) {
21
+ const network = this.shared.sequence.networks.find((network) => network.chainId === chainId);
22
+ if (!network) {
23
+ throw new Error(`Network not found for ${chainId}`);
24
+ }
25
+ const transport = RpcTransport.fromHttp(network.rpc);
26
+ const provider = Provider.from(transport);
27
+ const wallet = new Wallet(from, { stateProvider: this.shared.sequence.stateProvider });
28
+ const calls = txs.map((tx) => ({
29
+ to: tx.to,
30
+ value: tx.value ?? 0n,
31
+ data: tx.data ?? '0x',
32
+ gasLimit: tx.gasLimit ?? 0n, // TODO: Add gas estimation
33
+ delegateCall: false,
34
+ onlyFallback: false,
35
+ behaviorOnError: 'revert',
36
+ }));
37
+ const envelope = await wallet.prepareTransaction(provider, calls, {
38
+ noConfigUpdate: options?.noConfigUpdate,
39
+ });
40
+ const id = uuidv7();
41
+ await this.shared.databases.transactions.set({
42
+ id,
43
+ wallet: from,
44
+ requests: txs,
45
+ envelope,
46
+ source: options?.source ?? 'unknown',
47
+ status: 'requested',
48
+ });
49
+ return id;
50
+ }
51
+ async define(transactionId, changes) {
52
+ const tx = await this.get(transactionId);
53
+ if (tx.status !== 'requested') {
54
+ throw new Error(`Transaction ${transactionId} is not in the requested state`);
55
+ }
56
+ // Modify the envelope with the changes
57
+ if (changes?.nonce) {
58
+ tx.envelope.payload.nonce = changes.nonce;
59
+ }
60
+ if (changes?.space) {
61
+ tx.envelope.payload.space = changes.space;
62
+ }
63
+ if (changes?.calls) {
64
+ if (changes.calls.length !== tx.envelope.payload.calls.length) {
65
+ throw new Error(`Invalid number of calls for transaction ${transactionId}`);
66
+ }
67
+ for (let i = 0; i < changes.calls.length; i++) {
68
+ tx.envelope.payload.calls[i].gasLimit = changes.calls[i].gasLimit;
69
+ }
70
+ }
71
+ // Get relayer options
72
+ const allRelayerOptions = await Promise.all(this.shared.sequence.relayers.map(async (relayer) => {
73
+ const feeOptions = await relayer.feeOptions(tx.wallet, tx.envelope.chainId, tx.envelope.payload.calls);
74
+ if (feeOptions.options.length === 0) {
75
+ return [
76
+ {
77
+ id: uuidv7(),
78
+ relayerId: relayer.id,
79
+ },
80
+ ];
81
+ }
82
+ return feeOptions.options.map((feeOption) => ({
83
+ id: uuidv7(),
84
+ feeOption: feeOption,
85
+ relayerId: relayer.id,
86
+ quote: feeOptions.quote,
87
+ }));
88
+ }));
89
+ await this.shared.databases.transactions.set({
90
+ ...tx,
91
+ relayerOptions: allRelayerOptions.flat(),
92
+ status: 'defined',
93
+ });
94
+ }
95
+ async selectRelayer(transactionId, relayerOptionId) {
96
+ const tx = await this.get(transactionId);
97
+ if (tx.status !== 'defined') {
98
+ throw new Error(`Transaction ${transactionId} is not in the defined state`);
99
+ }
100
+ const selection = tx.relayerOptions.find((option) => option.id === relayerOptionId);
101
+ if (!selection) {
102
+ throw new Error(`Relayer option ${relayerOptionId} not found for transaction ${transactionId}`);
103
+ }
104
+ // Pass to the signatures manager
105
+ const signatureId = await this.shared.modules.signatures.request(tx.envelope, 'send-transaction', {
106
+ origin: tx.source,
107
+ });
108
+ await this.shared.databases.transactions.set({
109
+ ...tx,
110
+ relayerOptions: undefined,
111
+ relayerOption: selection,
112
+ status: 'formed',
113
+ signatureId,
114
+ });
115
+ return signatureId;
116
+ }
117
+ async relay(transactionOrSignatureId) {
118
+ // First, try to get the transaction directly
119
+ let tx;
120
+ try {
121
+ tx = await this.get(transactionOrSignatureId);
122
+ }
123
+ catch (e) {
124
+ // If not found, it might be a signature ID
125
+ const signature = await this.shared.modules.signatures.get(transactionOrSignatureId);
126
+ if (!signature) {
127
+ throw new Error(`Neither transaction nor signature found with ID ${transactionOrSignatureId}`);
128
+ }
129
+ // Find the transaction associated with this signature
130
+ const transactions = await this.list();
131
+ tx = transactions.find((t) => t.status === 'formed' && 'signatureId' in t && t.signatureId === transactionOrSignatureId);
132
+ if (!tx) {
133
+ throw new Error(`No transaction found for signature ${transactionOrSignatureId}`);
134
+ }
135
+ }
136
+ const transactionId = tx.id;
137
+ if (tx.status !== 'formed') {
138
+ throw new Error(`Transaction ${transactionId} is not in the formed state`);
139
+ }
140
+ const signature = await this.shared.modules.signatures.get(tx.signatureId);
141
+ if (!signature) {
142
+ throw new Error(`Signature ${tx.signatureId} not found for transaction ${transactionId}`);
143
+ }
144
+ const network = this.shared.sequence.networks.find((network) => network.chainId === tx.envelope.chainId);
145
+ if (!network) {
146
+ throw new Error(`Network not found for ${tx.envelope.chainId}`);
147
+ }
148
+ const transport = RpcTransport.fromHttp(network.rpc);
149
+ const provider = Provider.from(transport);
150
+ const wallet = new Wallet(tx.wallet, { stateProvider: this.shared.sequence.stateProvider });
151
+ if (!Payload.isCalls(signature.envelope.payload)) {
152
+ throw new Error(`Signature ${tx.signatureId} is not a calls payload`);
153
+ }
154
+ if (!Envelope.isSigned(signature.envelope)) {
155
+ throw new Error(`Transaction ${transactionId} is not signed`);
156
+ }
157
+ const { weight, threshold } = Envelope.weightOf(signature.envelope);
158
+ if (weight < threshold) {
159
+ throw new Error(`Transaction ${transactionId} has insufficient weight`);
160
+ }
161
+ const transaction = await wallet.buildTransaction(provider, signature.envelope);
162
+ const relayer = this.shared.sequence.relayers.find((relayer) => relayer.id === tx.relayerOption.relayerId);
163
+ if (!relayer) {
164
+ throw new Error(`Relayer ${tx.relayerOption.relayerId} not found for transaction ${transactionId}`);
165
+ }
166
+ const { opHash } = await relayer.relay(transaction.to, transaction.data, tx.envelope.chainId, tx.relayerOption.quote);
167
+ await this.shared.databases.transactions.set({
168
+ ...tx,
169
+ status: 'relayed',
170
+ opHash,
171
+ });
172
+ await this.shared.modules.signatures.complete(signature.id);
173
+ return opHash;
174
+ }
175
+ onTransactionsUpdate(cb, trigger) {
176
+ const undo = this.shared.databases.transactions.addListener(() => {
177
+ this.list().then((l) => cb(l));
178
+ });
179
+ if (trigger) {
180
+ this.list().then((l) => cb(l));
181
+ }
182
+ return undo;
183
+ }
184
+ onTransactionUpdate(transactionId, cb, trigger) {
185
+ const undo = this.shared.databases.transactions.addListener(() => {
186
+ this.get(transactionId).then((t) => cb(t));
187
+ });
188
+ if (trigger) {
189
+ this.get(transactionId).then((t) => cb(t));
190
+ }
191
+ return undo;
192
+ }
193
+ async delete(transactionId) {
194
+ const tx = await this.get(transactionId);
195
+ await this.shared.databases.transactions.del(transactionId);
196
+ // Cancel any signature requests associated with this transaction
197
+ if (tx.status === 'formed') {
198
+ await this.shared.modules.signatures.cancel(tx.signatureId);
199
+ }
200
+ }
201
+ }
@@ -0,0 +1,9 @@
1
+ export type { Message, MessageRequest, MessageRequested, MessageSigned } from './message-request.js';
2
+ export type { QueuedRecoveryPayload } from './recovery.js';
3
+ export { Actions } from './signature-request.js';
4
+ export type { Action, ActionToPayload, BaseSignatureRequest, SignatureRequest, Signer, SignerActionable, SignerBase, SignerReady, SignerSigned, SignerUnavailable, } from './signature-request.js';
5
+ export { Kinds } from './signer.js';
6
+ export type { Kind, RecoverySigner, SignerWithKind, WitnessExtraSignerKind } from './signer.js';
7
+ export type { RelayerOption, Transaction, TransactionDefined, TransactionFormed, TransactionRelayed, TransactionRequest, TransactionRequested, } from './transaction-request.js';
8
+ export type { Wallet } from './wallet.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sequence/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpG,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAChD,YAAY,EACV,MAAM,EACN,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,YAAY,EACZ,iBAAiB,GAClB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAC/F,YAAY,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { Actions } from './signature-request.js';
2
+ export { Kinds } from './signer.js';
@@ -0,0 +1,23 @@
1
+ import { Envelope } from '@0xsequence/wallet-core';
2
+ import { Payload } from '@0xsequence/wallet-primitives';
3
+ import { Address, Hex } from 'ox';
4
+ export type MessageRequest = string | Hex.Hex | Payload.TypedDataToSign;
5
+ type MessageBase = {
6
+ id: string;
7
+ wallet: Address.Address;
8
+ message: MessageRequest;
9
+ source: string;
10
+ signatureId: string;
11
+ };
12
+ export type MessageRequested = MessageBase & {
13
+ status: 'requested';
14
+ envelope: Envelope.Envelope<Payload.Message>;
15
+ };
16
+ export type MessageSigned = MessageBase & {
17
+ status: 'signed';
18
+ envelope: Envelope.Signed<Payload.Message>;
19
+ messageSignature: Hex.Hex;
20
+ };
21
+ export type Message = MessageRequested | MessageSigned;
22
+ export {};
23
+ //# sourceMappingURL=message-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-request.d.ts","sourceRoot":"","sources":["../../../src/sequence/types/message-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,IAAI,CAAA;AAEjC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,eAAe,CAAA;AAEvE,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAC,OAAO,CAAA;IACvB,OAAO,EAAE,cAAc,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG;IAC3C,MAAM,EAAE,WAAW,CAAA;IACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACxC,MAAM,EAAE,QAAQ,CAAA;IAChB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1C,gBAAgB,EAAE,GAAG,CAAC,GAAG,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,gBAAgB,GAAG,aAAa,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { Payload } from '@0xsequence/wallet-primitives';
2
+ import { Address, Hex } from 'ox';
3
+ export type QueuedRecoveryPayload = {
4
+ id: string;
5
+ index: bigint;
6
+ recoveryModule: Address.Address;
7
+ wallet: Address.Address;
8
+ signer: Address.Address;
9
+ chainId: bigint;
10
+ startTimestamp: bigint;
11
+ endTimestamp: bigint;
12
+ payloadHash: Hex.Hex;
13
+ payload?: Payload.Payload;
14
+ };
15
+ //# sourceMappingURL=recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../src/sequence/types/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,IAAI,CAAA;AAEjC,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,OAAO,CAAC,OAAO,CAAA;IAC/B,MAAM,EAAE,OAAO,CAAC,OAAO,CAAA;IACvB,MAAM,EAAE,OAAO,CAAC,OAAO,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,GAAG,CAAC,GAAG,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAA;CAC1B,CAAA"}
@@ -0,0 +1 @@
1
+ export {};