@0xsequence/wallet-core 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.
- package/.turbo/turbo-build.log +5 -0
- package/CHANGELOG.md +9 -0
- package/LICENSE +202 -0
- package/dist/envelope.d.ts +34 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +96 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/relayer/index.d.ts +4 -0
- package/dist/relayer/index.d.ts.map +1 -0
- package/dist/relayer/index.js +3 -0
- package/dist/relayer/local.d.ts +28 -0
- package/dist/relayer/local.d.ts.map +1 -0
- package/dist/relayer/local.js +101 -0
- package/dist/relayer/pk-relayer.d.ts +18 -0
- package/dist/relayer/pk-relayer.d.ts.map +1 -0
- package/dist/relayer/pk-relayer.js +88 -0
- package/dist/relayer/relayer.d.ts +39 -0
- package/dist/relayer/relayer.d.ts.map +1 -0
- package/dist/relayer/relayer.js +1 -0
- package/dist/signers/index.d.ts +23 -0
- package/dist/signers/index.d.ts.map +1 -0
- package/dist/signers/index.js +10 -0
- package/dist/signers/passkey.d.ts +41 -0
- package/dist/signers/passkey.d.ts.map +1 -0
- package/dist/signers/passkey.js +196 -0
- package/dist/signers/pk/encrypted.d.ts +37 -0
- package/dist/signers/pk/encrypted.d.ts.map +1 -0
- package/dist/signers/pk/encrypted.js +123 -0
- package/dist/signers/pk/index.d.ts +35 -0
- package/dist/signers/pk/index.d.ts.map +1 -0
- package/dist/signers/pk/index.js +51 -0
- package/dist/signers/session/explicit.d.ts +18 -0
- package/dist/signers/session/explicit.d.ts.map +1 -0
- package/dist/signers/session/explicit.js +126 -0
- package/dist/signers/session/implicit.d.ts +20 -0
- package/dist/signers/session/implicit.d.ts.map +1 -0
- package/dist/signers/session/implicit.js +120 -0
- package/dist/signers/session/index.d.ts +4 -0
- package/dist/signers/session/index.d.ts.map +1 -0
- package/dist/signers/session/index.js +3 -0
- package/dist/signers/session/session.d.ts +11 -0
- package/dist/signers/session/session.d.ts.map +1 -0
- package/dist/signers/session/session.js +1 -0
- package/dist/signers/session-manager.d.ts +33 -0
- package/dist/signers/session-manager.d.ts.map +1 -0
- package/dist/signers/session-manager.js +181 -0
- package/dist/state/cached.d.ts +59 -0
- package/dist/state/cached.d.ts.map +1 -0
- package/dist/state/cached.js +157 -0
- package/dist/state/index.d.ts +61 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +4 -0
- package/dist/state/local/index.d.ts +98 -0
- package/dist/state/local/index.d.ts.map +1 -0
- package/dist/state/local/index.js +247 -0
- package/dist/state/local/indexed-db.d.ts +41 -0
- package/dist/state/local/indexed-db.d.ts.map +1 -0
- package/dist/state/local/indexed-db.js +149 -0
- package/dist/state/local/memory.d.ts +41 -0
- package/dist/state/local/memory.d.ts.map +1 -0
- package/dist/state/local/memory.js +77 -0
- package/dist/state/remote/dev-http.d.ts +57 -0
- package/dist/state/remote/dev-http.d.ts.map +1 -0
- package/dist/state/remote/dev-http.js +162 -0
- package/dist/state/remote/index.d.ts +2 -0
- package/dist/state/remote/index.d.ts.map +1 -0
- package/dist/state/remote/index.js +1 -0
- package/dist/state/utils.d.ts +12 -0
- package/dist/state/utils.d.ts.map +1 -0
- package/dist/state/utils.js +29 -0
- package/dist/wallet.d.ts +58 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +306 -0
- package/package.json +33 -0
- package/src/envelope.ts +148 -0
- package/src/index.ts +6 -0
- package/src/relayer/index.ts +3 -0
- package/src/relayer/local.ts +125 -0
- package/src/relayer/pk-relayer.ts +110 -0
- package/src/relayer/relayer.ts +52 -0
- package/src/signers/index.ts +44 -0
- package/src/signers/passkey.ts +284 -0
- package/src/signers/pk/encrypted.ts +153 -0
- package/src/signers/pk/index.ts +77 -0
- package/src/signers/session/explicit.ts +173 -0
- package/src/signers/session/implicit.ts +145 -0
- package/src/signers/session/index.ts +3 -0
- package/src/signers/session/session.ts +26 -0
- package/src/signers/session-manager.ts +241 -0
- package/src/state/cached.ts +233 -0
- package/src/state/index.ts +85 -0
- package/src/state/local/index.ts +422 -0
- package/src/state/local/indexed-db.ts +204 -0
- package/src/state/local/memory.ts +126 -0
- package/src/state/remote/dev-http.ts +253 -0
- package/src/state/remote/index.ts +1 -0
- package/src/state/utils.ts +50 -0
- package/src/wallet.ts +390 -0
- package/test/constants.ts +15 -0
- package/test/session-manager.test.ts +451 -0
- package/test/setup.ts +63 -0
- package/test/wallet.test.ts +90 -0
- package/tsconfig.json +10 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Context, Payload, Signature, Config, GenericTree } from '@0xsequence/wallet-primitives'
|
|
2
|
+
import { Address, Hex } from 'ox'
|
|
3
|
+
import { Store } from './index.js'
|
|
4
|
+
|
|
5
|
+
export class MemoryStore implements Store {
|
|
6
|
+
private configs = new Map<`0x${string}`, Config.Config>()
|
|
7
|
+
private counterfactualWallets = new Map<`0x${string}`, { imageHash: Hex.Hex; context: Context.Context }>()
|
|
8
|
+
private payloads = new Map<`0x${string}`, { content: Payload.Parented; chainId: bigint; wallet: Address.Address }>()
|
|
9
|
+
private signerSubdigests = new Map<string, Set<string>>()
|
|
10
|
+
private signatures = new Map<`0x${string}`, Signature.SignatureOfSignerLeaf>()
|
|
11
|
+
|
|
12
|
+
private sapientSignerSubdigests = new Map<string, Set<string>>()
|
|
13
|
+
private sapientSignatures = new Map<`0x${string}`, Signature.SignatureOfSapientSignerLeaf>()
|
|
14
|
+
|
|
15
|
+
private trees = new Map<`0x${string}`, GenericTree.Tree>()
|
|
16
|
+
|
|
17
|
+
private getSignatureKey(signer: Address.Address, subdigest: Hex.Hex): string {
|
|
18
|
+
return `${signer.toLowerCase()}-${subdigest.toLowerCase()}`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private getSapientSignatureKey(signer: Address.Address, subdigest: Hex.Hex, imageHash: Hex.Hex): string {
|
|
22
|
+
return `${signer.toLowerCase()}-${imageHash.toLowerCase()}-${subdigest.toLowerCase()}`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async loadConfig(imageHash: Hex.Hex): Promise<Config.Config | undefined> {
|
|
26
|
+
return this.configs.get(imageHash.toLowerCase() as `0x${string}`)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async saveConfig(imageHash: Hex.Hex, config: Config.Config): Promise<void> {
|
|
30
|
+
this.configs.set(imageHash.toLowerCase() as `0x${string}`, config)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async loadCounterfactualWallet(
|
|
34
|
+
wallet: Address.Address,
|
|
35
|
+
): Promise<{ imageHash: Hex.Hex; context: Context.Context } | undefined> {
|
|
36
|
+
return this.counterfactualWallets.get(wallet.toLowerCase() as `0x${string}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async saveCounterfactualWallet(wallet: Address.Address, imageHash: Hex.Hex, context: Context.Context): Promise<void> {
|
|
40
|
+
this.counterfactualWallets.set(wallet.toLowerCase() as `0x${string}`, { imageHash, context })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async loadPayloadOfSubdigest(
|
|
44
|
+
subdigest: Hex.Hex,
|
|
45
|
+
): Promise<{ content: Payload.Parented; chainId: bigint; wallet: Address.Address } | undefined> {
|
|
46
|
+
return this.payloads.get(subdigest.toLowerCase() as `0x${string}`)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async savePayloadOfSubdigest(
|
|
50
|
+
subdigest: Hex.Hex,
|
|
51
|
+
payload: { content: Payload.Parented; chainId: bigint; wallet: Address.Address },
|
|
52
|
+
): Promise<void> {
|
|
53
|
+
this.payloads.set(subdigest.toLowerCase() as `0x${string}`, payload)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async loadSubdigestsOfSigner(signer: Address.Address): Promise<Hex.Hex[]> {
|
|
57
|
+
const subdigests = this.signerSubdigests.get(signer.toLowerCase() as `0x${string}`)
|
|
58
|
+
return subdigests ? Array.from(subdigests).map((s) => s as Hex.Hex) : []
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async loadSignatureOfSubdigest(
|
|
62
|
+
signer: Address.Address,
|
|
63
|
+
subdigest: Hex.Hex,
|
|
64
|
+
): Promise<Signature.SignatureOfSignerLeaf | undefined> {
|
|
65
|
+
const key = this.getSignatureKey(signer, subdigest)
|
|
66
|
+
return this.signatures.get(key as `0x${string}`)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async saveSignatureOfSubdigest(
|
|
70
|
+
signer: Address.Address,
|
|
71
|
+
subdigest: Hex.Hex,
|
|
72
|
+
signature: Signature.SignatureOfSignerLeaf,
|
|
73
|
+
): Promise<void> {
|
|
74
|
+
const key = this.getSignatureKey(signer, subdigest)
|
|
75
|
+
this.signatures.set(key as `0x${string}`, signature)
|
|
76
|
+
|
|
77
|
+
const signerKey = signer.toLowerCase()
|
|
78
|
+
const subdigestKey = subdigest.toLowerCase()
|
|
79
|
+
|
|
80
|
+
if (!this.signerSubdigests.has(signerKey)) {
|
|
81
|
+
this.signerSubdigests.set(signerKey, new Set())
|
|
82
|
+
}
|
|
83
|
+
this.signerSubdigests.get(signerKey)!.add(subdigestKey)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async loadSubdigestsOfSapientSigner(signer: Address.Address, imageHash: Hex.Hex): Promise<Hex.Hex[]> {
|
|
87
|
+
const key = `${signer.toLowerCase()}-${imageHash.toLowerCase()}`
|
|
88
|
+
const subdigests = this.sapientSignerSubdigests.get(key)
|
|
89
|
+
return subdigests ? Array.from(subdigests).map((s) => s as Hex.Hex) : []
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async loadSapientSignatureOfSubdigest(
|
|
93
|
+
signer: Address.Address,
|
|
94
|
+
subdigest: Hex.Hex,
|
|
95
|
+
imageHash: Hex.Hex,
|
|
96
|
+
): Promise<Signature.SignatureOfSapientSignerLeaf | undefined> {
|
|
97
|
+
const key = this.getSapientSignatureKey(signer, subdigest, imageHash)
|
|
98
|
+
return this.sapientSignatures.get(key as `0x${string}`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async saveSapientSignatureOfSubdigest(
|
|
102
|
+
signer: Address.Address,
|
|
103
|
+
subdigest: Hex.Hex,
|
|
104
|
+
imageHash: Hex.Hex,
|
|
105
|
+
signature: Signature.SignatureOfSapientSignerLeaf,
|
|
106
|
+
): Promise<void> {
|
|
107
|
+
const key = this.getSapientSignatureKey(signer, subdigest, imageHash)
|
|
108
|
+
this.sapientSignatures.set(key as `0x${string}`, signature)
|
|
109
|
+
|
|
110
|
+
const signerKey = `${signer.toLowerCase()}-${imageHash.toLowerCase()}`
|
|
111
|
+
const subdigestKey = subdigest.toLowerCase()
|
|
112
|
+
|
|
113
|
+
if (!this.sapientSignerSubdigests.has(signerKey)) {
|
|
114
|
+
this.sapientSignerSubdigests.set(signerKey, new Set())
|
|
115
|
+
}
|
|
116
|
+
this.sapientSignerSubdigests.get(signerKey)!.add(subdigestKey)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async loadTree(rootHash: Hex.Hex): Promise<GenericTree.Tree | undefined> {
|
|
120
|
+
return this.trees.get(rootHash.toLowerCase() as `0x${string}`)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async saveTree(rootHash: Hex.Hex, tree: GenericTree.Tree): Promise<void> {
|
|
124
|
+
this.trees.set(rootHash.toLowerCase() as `0x${string}`, tree)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { Address, Hex } from 'ox'
|
|
2
|
+
import { Config, Context, GenericTree, Payload, Signature, Utils } from '@0xsequence/wallet-primitives'
|
|
3
|
+
import { Provider } from '../index.js'
|
|
4
|
+
|
|
5
|
+
export class DevHttpProvider implements Provider {
|
|
6
|
+
private readonly baseUrl: string
|
|
7
|
+
|
|
8
|
+
constructor(baseUrl: string) {
|
|
9
|
+
// Remove trailing slash if present
|
|
10
|
+
this.baseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
private async request<T>(method: 'GET' | 'POST', path: string, body?: any): Promise<T> {
|
|
14
|
+
const url = `${this.baseUrl}${path}`
|
|
15
|
+
const options: RequestInit = {
|
|
16
|
+
method,
|
|
17
|
+
headers: {},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (body && method === 'POST') {
|
|
21
|
+
options.headers = { 'Content-Type': 'application/json' }
|
|
22
|
+
options.body = Utils.toJSON(body)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let response: Response
|
|
26
|
+
try {
|
|
27
|
+
response = await fetch(url, options)
|
|
28
|
+
} catch (networkError) {
|
|
29
|
+
// Handle immediate network errors (e.g., DNS resolution failure, refused connection)
|
|
30
|
+
console.error(`Network error during ${method} request to ${url}:`, networkError)
|
|
31
|
+
throw networkError // Re-throw network errors
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// --- Error Handling for HTTP Status ---
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
let errorPayload: any = { message: `HTTP error! Status: ${response.status}` }
|
|
37
|
+
try {
|
|
38
|
+
const errorText = await response.text()
|
|
39
|
+
const errorJson = await Utils.fromJSON(errorText)
|
|
40
|
+
errorPayload = { ...errorPayload, ...errorJson }
|
|
41
|
+
} catch (e) {
|
|
42
|
+
try {
|
|
43
|
+
// If JSON parsing fails, try getting text for better error message
|
|
44
|
+
const errorText = await response.text()
|
|
45
|
+
errorPayload.body = errorText
|
|
46
|
+
} catch (textErr) {
|
|
47
|
+
// Ignore if reading text also fails
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
console.error('HTTP Request Failed:', errorPayload)
|
|
51
|
+
throw new Error(errorPayload.message || `Request failed for ${method} ${path} with status ${response.status}`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// --- Response Body Handling (with fix for empty body) ---
|
|
55
|
+
try {
|
|
56
|
+
// Handle cases where POST might return 201/204 No Content
|
|
57
|
+
// 204 should definitely have no body. 201 might or might not.
|
|
58
|
+
if (response.status === 204) {
|
|
59
|
+
return undefined as T // No content expected
|
|
60
|
+
}
|
|
61
|
+
if (response.status === 201 && method === 'POST') {
|
|
62
|
+
// Attempt to parse JSON (e.g., for { success: true }), but handle empty body gracefully
|
|
63
|
+
const text = await response.clone().text() // Clone and check text first
|
|
64
|
+
if (text.trim() === '') {
|
|
65
|
+
return undefined as T // Treat empty 201 as success with no specific return data
|
|
66
|
+
}
|
|
67
|
+
// If not empty, try parsing JSON
|
|
68
|
+
const responseText = await response.text()
|
|
69
|
+
return (await Utils.fromJSON(responseText)) as T
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// For 200 OK or other success statuses expecting a body
|
|
73
|
+
// Clone the response before attempting to read the body,
|
|
74
|
+
// so we can potentially read it again (as text) if json() fails.
|
|
75
|
+
const clonedResponse = response.clone()
|
|
76
|
+
const textContent = await clonedResponse.text() // Read as text first
|
|
77
|
+
|
|
78
|
+
if (textContent.trim() === '') {
|
|
79
|
+
// If the body is empty (or only whitespace) and status was OK (checked above),
|
|
80
|
+
// treat this as the server sending 'undefined' or 'null'.
|
|
81
|
+
// Return `undefined` to match the expected optional types in the Provider interface.
|
|
82
|
+
return undefined as T
|
|
83
|
+
} else {
|
|
84
|
+
// If there is content, attempt to parse it as JSON.
|
|
85
|
+
// We use the original response here, which hasn't had its body consumed yet.
|
|
86
|
+
const responseText = await response.text()
|
|
87
|
+
const data = await Utils.fromJSON(responseText)
|
|
88
|
+
|
|
89
|
+
// BigInt Deserialization note remains the same: manual conversion may be needed by consumer.
|
|
90
|
+
return data as T
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
// This catch block now primarily handles errors from response.json()
|
|
94
|
+
// if the non-empty textContent wasn't valid JSON.
|
|
95
|
+
console.error(`Error processing response body for ${method} ${url}:`, error)
|
|
96
|
+
// Also include the raw text in the error if possible
|
|
97
|
+
try {
|
|
98
|
+
const text = await response.text() // Try reading original response if not already done
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Failed to parse JSON response from server. Status: ${response.status}. Body: "${text}". Original error: ${error instanceof Error ? error.message : String(error)}`,
|
|
101
|
+
)
|
|
102
|
+
} catch (readError) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Failed to parse JSON response from server and could not read response body as text. Status: ${response.status}. Original error: ${error instanceof Error ? error.message : String(error)}`,
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// --- Reader Methods ---
|
|
111
|
+
|
|
112
|
+
async getConfiguration(imageHash: Hex.Hex): Promise<Config.Config | undefined> {
|
|
113
|
+
// The response needs careful handling if BigInts are involved (threshold, checkpoint)
|
|
114
|
+
const config = await this.request<Config.Config | undefined>('GET', `/configuration/${imageHash}`)
|
|
115
|
+
// Manual conversion example (if needed by consumer):
|
|
116
|
+
// if (config?.threshold) config.threshold = BigInt(config.threshold);
|
|
117
|
+
// if (config?.checkpoint) config.checkpoint = BigInt(config.checkpoint);
|
|
118
|
+
return config
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async getDeploy(wallet: Address.Address): Promise<{ imageHash: Hex.Hex; context: Context.Context } | undefined> {
|
|
122
|
+
return this.request('GET', `/deploy/${wallet}`)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async getWallets(signer: Address.Address): Promise<{
|
|
126
|
+
[wallet: Address.Address]: {
|
|
127
|
+
chainId: bigint
|
|
128
|
+
payload: Payload.Parented
|
|
129
|
+
signature: Signature.SignatureOfSignerLeaf
|
|
130
|
+
}
|
|
131
|
+
}> {
|
|
132
|
+
// Response `chainId` will be a string/number, needs conversion if BigInt is strictly required upstream
|
|
133
|
+
return this.request('GET', `/wallets/signer/${signer}`)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async getWalletsForSapient(
|
|
137
|
+
signer: Address.Address,
|
|
138
|
+
imageHash: Hex.Hex,
|
|
139
|
+
): Promise<{
|
|
140
|
+
[wallet: Address.Address]: {
|
|
141
|
+
chainId: bigint
|
|
142
|
+
payload: Payload.Parented
|
|
143
|
+
signature: Signature.SignatureOfSapientSignerLeaf
|
|
144
|
+
}
|
|
145
|
+
}> {
|
|
146
|
+
// Response `chainId` will be a string/number, needs conversion
|
|
147
|
+
return this.request('GET', `/wallets/sapient/${signer}/${imageHash}`)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async getWitnessFor(
|
|
151
|
+
wallet: Address.Address,
|
|
152
|
+
signer: Address.Address,
|
|
153
|
+
): Promise<
|
|
154
|
+
| {
|
|
155
|
+
chainId: bigint
|
|
156
|
+
payload: Payload.Parented
|
|
157
|
+
signature: Signature.SignatureOfSignerLeaf
|
|
158
|
+
}
|
|
159
|
+
| undefined
|
|
160
|
+
> {
|
|
161
|
+
// Response `chainId` will be a string/number, needs conversion
|
|
162
|
+
return this.request('GET', `/witness/${wallet}/signer/${signer}`)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async getWitnessForSapient(
|
|
166
|
+
wallet: Address.Address,
|
|
167
|
+
signer: Address.Address,
|
|
168
|
+
imageHash: Hex.Hex,
|
|
169
|
+
): Promise<
|
|
170
|
+
| {
|
|
171
|
+
chainId: bigint
|
|
172
|
+
payload: Payload.Parented
|
|
173
|
+
signature: Signature.SignatureOfSapientSignerLeaf
|
|
174
|
+
}
|
|
175
|
+
| undefined
|
|
176
|
+
> {
|
|
177
|
+
// Response `chainId` will be a string/number, needs conversion
|
|
178
|
+
return this.request('GET', `/witness/sapient/${wallet}/${signer}/${imageHash}`)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async getConfigurationUpdates(
|
|
182
|
+
wallet: Address.Address,
|
|
183
|
+
fromImageHash: Hex.Hex,
|
|
184
|
+
options?: { allUpdates?: boolean },
|
|
185
|
+
): Promise<Array<{ imageHash: Hex.Hex; signature: Signature.RawSignature }>> {
|
|
186
|
+
const query = options?.allUpdates ? '?allUpdates=true' : ''
|
|
187
|
+
// Response signature object might contain BigInts (threshold, checkpoint) as strings
|
|
188
|
+
return this.request('GET', `/configuration-updates/${wallet}/from/${fromImageHash}${query}`)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async getTree(rootHash: Hex.Hex): Promise<GenericTree.Tree | undefined> {
|
|
192
|
+
return this.request('GET', `/tree/${rootHash}`)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// --- Writer Methods ---
|
|
196
|
+
|
|
197
|
+
async saveWallet(deployConfiguration: Config.Config, context: Context.Context): Promise<void> {
|
|
198
|
+
await this.request<void>('POST', '/wallet', { deployConfiguration, context })
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async saveWitnesses(
|
|
202
|
+
wallet: Address.Address,
|
|
203
|
+
chainId: bigint,
|
|
204
|
+
payload: Payload.Parented,
|
|
205
|
+
signatures: Signature.RawTopology,
|
|
206
|
+
): Promise<void> {
|
|
207
|
+
// chainId will be correctly stringified by the jsonReplacer
|
|
208
|
+
await this.request<void>('POST', '/witnesses', { wallet, chainId, payload, signatures })
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async saveUpdate(
|
|
212
|
+
wallet: Address.Address,
|
|
213
|
+
configuration: Config.Config,
|
|
214
|
+
signature: Signature.RawSignature,
|
|
215
|
+
): Promise<void> {
|
|
216
|
+
// configuration and signature might contain BigInts, handled by replacer
|
|
217
|
+
await this.request<void>('POST', '/update', { wallet, configuration, signature })
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async saveTree(tree: GenericTree.Tree): Promise<void> {
|
|
221
|
+
await this.request<void>('POST', '/tree', { tree })
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
saveConfiguration(config: Config.Config): Promise<void> {
|
|
225
|
+
return this.request<void>('POST', '/configuration', { config })
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
saveDeploy(imageHash: Hex.Hex, context: Context.Context): Promise<void> {
|
|
229
|
+
return this.request<void>('POST', '/deploy', { imageHash, context })
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async getPayload(opHash: Hex.Hex): Promise<
|
|
233
|
+
| {
|
|
234
|
+
chainId: bigint
|
|
235
|
+
payload: Payload.Parented
|
|
236
|
+
wallet: Address.Address
|
|
237
|
+
}
|
|
238
|
+
| undefined
|
|
239
|
+
> {
|
|
240
|
+
return this.request<
|
|
241
|
+
| {
|
|
242
|
+
chainId: bigint
|
|
243
|
+
payload: Payload.Parented
|
|
244
|
+
wallet: Address.Address
|
|
245
|
+
}
|
|
246
|
+
| undefined
|
|
247
|
+
>('GET', `/payload/${opHash}`)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async savePayload(wallet: Address.Address, payload: Payload.Parented, chainId: bigint): Promise<void> {
|
|
251
|
+
return this.request<void>('POST', '/payload', { wallet, payload, chainId })
|
|
252
|
+
}
|
|
253
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dev-http.js'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Payload, Signature } from '@0xsequence/wallet-primitives'
|
|
2
|
+
import { Address, Hex } from 'ox'
|
|
3
|
+
import { Reader } from './index.js'
|
|
4
|
+
import { isSapientSigner, SapientSigner, Signer } from '../signers/index.js'
|
|
5
|
+
|
|
6
|
+
export type WalletWithWitness<S extends Signer | SapientSigner> = {
|
|
7
|
+
wallet: Address.Address
|
|
8
|
+
chainId: bigint
|
|
9
|
+
payload: Payload.Parented
|
|
10
|
+
signature: S extends SapientSigner ? Signature.SignatureOfSapientSignerLeaf : Signature.SignatureOfSignerLeaf
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function getWalletsFor<S extends Signer | SapientSigner>(
|
|
14
|
+
stateReader: Reader,
|
|
15
|
+
signer: S,
|
|
16
|
+
): Promise<Array<WalletWithWitness<S>>> {
|
|
17
|
+
const wallets = await retrieveWallets(stateReader, signer)
|
|
18
|
+
return Object.entries(wallets).map(([wallet, { chainId, payload, signature }]) => {
|
|
19
|
+
Hex.assert(wallet)
|
|
20
|
+
return {
|
|
21
|
+
wallet,
|
|
22
|
+
chainId,
|
|
23
|
+
payload,
|
|
24
|
+
signature,
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function retrieveWallets<S extends Signer | SapientSigner>(
|
|
30
|
+
stateReader: Reader,
|
|
31
|
+
signer: S,
|
|
32
|
+
): Promise<{
|
|
33
|
+
[wallet: `0x${string}`]: {
|
|
34
|
+
chainId: bigint
|
|
35
|
+
payload: Payload.Parented
|
|
36
|
+
signature: S extends SapientSigner ? Signature.SignatureOfSapientSignerLeaf : Signature.SignatureOfSignerLeaf
|
|
37
|
+
}
|
|
38
|
+
}> {
|
|
39
|
+
if (isSapientSigner(signer)) {
|
|
40
|
+
const [signerAddress, signerImageHash] = await Promise.all([signer.address, signer.imageHash])
|
|
41
|
+
if (signerImageHash) {
|
|
42
|
+
return stateReader.getWalletsForSapient(signerAddress, signerImageHash) as unknown as any
|
|
43
|
+
} else {
|
|
44
|
+
console.warn('Sapient signer has no imageHash')
|
|
45
|
+
return {} as any
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
return stateReader.getWallets(await signer.address) as unknown as any
|
|
49
|
+
}
|
|
50
|
+
}
|