passkey-kit 0.11.2 → 0.12.0
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/.claude/settings.local.json +20 -0
- package/PROPOSAL.md +1 -1
- package/README.md +287 -54
- package/package.json +4 -3
- package/src/kit.ts +13 -3
- package/src/server.ts +29 -49
- package/types/kit.d.ts +4 -1
- package/types/server.d.ts +6 -7
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"WebSearch",
|
|
5
|
+
"mcp__context7__resolve-library-id",
|
|
6
|
+
"Bash(tree:*)",
|
|
7
|
+
"mcp__deepwiki__read_wiki_structure",
|
|
8
|
+
"mcp__context7__query-docs",
|
|
9
|
+
"mcp__deepwiki__read_wiki_contents",
|
|
10
|
+
"Bash(curl:*)",
|
|
11
|
+
"Bash(pnpm install:*)",
|
|
12
|
+
"Bash(pnpm run build:*)",
|
|
13
|
+
"mcp__github__get_file_contents",
|
|
14
|
+
"mcp__perplexity__perplexity_ask",
|
|
15
|
+
"mcp__perplexity__perplexity_search"
|
|
16
|
+
],
|
|
17
|
+
"deny": [],
|
|
18
|
+
"ask": []
|
|
19
|
+
}
|
|
20
|
+
}
|
package/PROPOSAL.md
CHANGED
|
@@ -6,7 +6,7 @@ Over the past months I've been hard at work designing a solid first stab at a v1
|
|
|
6
6
|
|
|
7
7
|
All the best work can reviewed in my [passkey-kit](https://github.com/kalepail/passkey-kit) repo. This repo includes the factory and wallet contracts, a demo client interface, a `passkey-kit` SDK tool to make interacting with the contract interface simple and painless and finally a [Mercury Zephyr](https://www.mercurydata.app/products/zephyr-vm) program for indexing contract events in order to make the wallet more usable client side.
|
|
8
8
|
|
|
9
|
-
This repo also makes use of
|
|
9
|
+
This repo also makes use of the [OpenZeppelin Relayer service](https://docs.openzeppelin.com/relayer/1.3.x/guides/stellar-channels-guide) which makes submitting Soroban transactions simple by handling the concerns of both transaction fees and sequence numbers.
|
|
10
10
|
|
|
11
11
|
The primary interest of this proposal is to detail the contract interface itself but many of the design decisions are informed by complexities and available solutions external to the interface. A well rounded understandings of all that's involved to make passkey powered smart wallets on Stellar actually work is necessary in order to arrive at a truly viable contract interface.
|
|
12
12
|
|
package/README.md
CHANGED
|
@@ -1,106 +1,339 @@
|
|
|
1
1
|
# Passkey Kit
|
|
2
2
|
|
|
3
|
-
> [!
|
|
3
|
+
> [!TIP]
|
|
4
|
+
> **Looking for the latest smart wallet SDK?**
|
|
5
|
+
>
|
|
6
|
+
> This package is the **legacy precursor** to [OpenZeppelin Smart Accounts](https://docs.openzeppelin.com/stellar-contracts/accounts/smart-account). For new projects, use **[smart-account-kit](https://github.com/kalepail/smart-account-kit)** — a comprehensive SDK built on top of the audited [OpenZeppelin stellar-contracts](https://github.com/OpenZeppelin/stellar-contracts) library.
|
|
7
|
+
>
|
|
8
|
+
> Smart Account Kit includes:
|
|
9
|
+
> - Context rules with fine-grained authorization scopes
|
|
10
|
+
> - Policy support (threshold multisig, spending limits, custom policies)
|
|
11
|
+
> - Session management with automatic credential persistence
|
|
12
|
+
> - External wallet adapter support
|
|
13
|
+
> - Built-in indexer for contract discovery
|
|
14
|
+
>
|
|
15
|
+
> See the [OpenZeppelin Smart Account package](https://github.com/OpenZeppelin/stellar-contracts/tree/main/packages/accounts) and [multisig example](https://github.com/OpenZeppelin/stellar-contracts/tree/main/examples/multisig-smart-account/account) for more details.
|
|
16
|
+
|
|
17
|
+
> [!WARNING]
|
|
4
18
|
> Code in this repo is demo material only. It has not been audited. Do not use to hold, protect, or secure anything.
|
|
5
19
|
|
|
6
|
-
|
|
20
|
+
A TypeScript SDK for creating and managing Stellar smart wallets using passkeys. Works with [OpenZeppelin Relayer](https://docs.openzeppelin.com/relayer/1.3.x/guides/stellar-channels-guide) for submitting passkey-signed transactions onchain.
|
|
7
21
|
|
|
8
|
-
Demo
|
|
22
|
+
**Demo:** [passkey-kit-demo.pages.dev](https://passkey-kit-demo.pages.dev/)
|
|
9
23
|
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
12
27
|
pnpm i passkey-kit
|
|
13
28
|
```
|
|
14
29
|
|
|
15
|
-
|
|
30
|
+
## Exports
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import {
|
|
34
|
+
PasskeyKit, // Client-side wallet management
|
|
35
|
+
PasskeyServer, // Server-side utilities
|
|
36
|
+
SACClient, // Stellar Asset Contract helper
|
|
37
|
+
PasskeyClient, // Low-level contract client (from passkey-kit-sdk)
|
|
38
|
+
SignerKey, // Signer key type constructor
|
|
39
|
+
SignerStore, // Storage type enum
|
|
40
|
+
type Signer, // Signer type
|
|
41
|
+
type SignerLimits // Signer limits type
|
|
42
|
+
} from 'passkey-kit'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## PasskeyKit (Client)
|
|
48
|
+
|
|
49
|
+
Handles wallet creation, connection, and transaction signing.
|
|
50
|
+
|
|
51
|
+
### Constructor
|
|
52
|
+
|
|
16
53
|
```ts
|
|
17
54
|
const account = new PasskeyKit({
|
|
18
|
-
rpcUrl:
|
|
19
|
-
networkPassphrase:
|
|
20
|
-
|
|
21
|
-
|
|
55
|
+
rpcUrl: string, // Stellar RPC URL
|
|
56
|
+
networkPassphrase: string, // Network passphrase
|
|
57
|
+
walletWasmHash: string, // Smart wallet WASM hash
|
|
58
|
+
timeoutInSeconds?: number, // Transaction timeout (default: 30)
|
|
59
|
+
WebAuthn?: { // Optional WebAuthn override
|
|
60
|
+
startRegistration,
|
|
61
|
+
startAuthentication
|
|
62
|
+
}
|
|
63
|
+
})
|
|
22
64
|
```
|
|
23
65
|
|
|
24
|
-
|
|
66
|
+
### Properties
|
|
67
|
+
|
|
68
|
+
| Property | Type | Description |
|
|
69
|
+
|----------|------|-------------|
|
|
70
|
+
| `keyId` | `string \| undefined` | Current passkey ID (base64url) |
|
|
71
|
+
| `wallet` | `PasskeyClient \| undefined` | Connected wallet client |
|
|
72
|
+
| `networkPassphrase` | `string` | Network passphrase |
|
|
73
|
+
|
|
74
|
+
### Methods
|
|
75
|
+
|
|
76
|
+
#### `createWallet(app, user, settings?)`
|
|
77
|
+
Creates a new passkey and deploys a smart wallet.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
const { rawResponse, keyId, keyIdBase64, contractId, signedTx } = await account.createWallet(
|
|
81
|
+
'My App', // App name shown in passkey prompt
|
|
82
|
+
'user@example.com', // User identifier
|
|
83
|
+
{
|
|
84
|
+
rpId?: string, // Relying party ID
|
|
85
|
+
authenticatorSelection?: AuthenticatorSelectionCriteria
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### `createKey(app, user, settings?)`
|
|
91
|
+
Creates a new passkey without deploying a wallet.
|
|
92
|
+
|
|
25
93
|
```ts
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
mercuryJwt: env.PRIVATE_mercuryJwt,
|
|
32
|
-
});
|
|
94
|
+
const { rawResponse, keyId, keyIdBase64, publicKey } = await account.createKey(
|
|
95
|
+
'My App',
|
|
96
|
+
'user@example.com',
|
|
97
|
+
{ rpId?: string, authenticatorSelection?: AuthenticatorSelectionCriteria }
|
|
98
|
+
)
|
|
33
99
|
```
|
|
34
100
|
|
|
35
|
-
|
|
101
|
+
#### `connectWallet(opts?)`
|
|
102
|
+
Connects to an existing wallet using a passkey.
|
|
36
103
|
|
|
37
|
-
|
|
104
|
+
```ts
|
|
105
|
+
const { rawResponse, keyId, keyIdBase64, contractId } = await account.connectWallet({
|
|
106
|
+
rpId?: string,
|
|
107
|
+
keyId?: string | Uint8Array, // Skip passkey prompt if provided
|
|
108
|
+
getContractId?: (keyId: string) => Promise<string | undefined>, // Lookup function
|
|
109
|
+
walletPublicKey?: string // For backwards compatibility
|
|
110
|
+
})
|
|
111
|
+
```
|
|
38
112
|
|
|
39
|
-
|
|
113
|
+
#### `sign(txn, options?)`
|
|
114
|
+
Signs all auth entries for the connected wallet in a transaction.
|
|
40
115
|
|
|
41
|
-
|
|
116
|
+
```ts
|
|
117
|
+
const signedTxn = await account.sign(
|
|
118
|
+
txn, // AssembledTransaction | Tx | string (XDR)
|
|
119
|
+
{
|
|
120
|
+
rpId?: string,
|
|
121
|
+
keyId?: 'any' | string | Uint8Array, // 'any' allows any passkey
|
|
122
|
+
keypair?: Keypair, // Sign with Ed25519 instead
|
|
123
|
+
policy?: string, // Sign with policy instead
|
|
124
|
+
expiration?: number // Ledger expiration
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
```
|
|
42
128
|
|
|
43
|
-
|
|
129
|
+
#### `signAuthEntry(entry, options?)`
|
|
130
|
+
Signs a single authorization entry. Same options as `sign()`.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const signedEntry = await account.signAuthEntry(entry, options)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Signer Management
|
|
137
|
+
|
|
138
|
+
Add, update, or remove signers from the wallet.
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
// Add signers
|
|
142
|
+
await account.addSecp256r1(keyId, publicKey, limits, store, expiration?)
|
|
143
|
+
await account.addEd25519(publicKey, limits, store, expiration?)
|
|
144
|
+
await account.addPolicy(policy, limits, store, expiration?)
|
|
145
|
+
|
|
146
|
+
// Update signers
|
|
147
|
+
await account.updateSecp256r1(keyId, publicKey, limits, store, expiration?)
|
|
148
|
+
await account.updateEd25519(publicKey, limits, store, expiration?)
|
|
149
|
+
await account.updatePolicy(policy, limits, store, expiration?)
|
|
150
|
+
|
|
151
|
+
// Remove signer
|
|
152
|
+
await account.remove(signerKey)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Parameters:**
|
|
156
|
+
- `keyId` - Passkey ID (string or Uint8Array)
|
|
157
|
+
- `publicKey` - Public key (string or Uint8Array for Secp256r1, Stellar public key for Ed25519)
|
|
158
|
+
- `policy` - Policy contract address
|
|
159
|
+
- `limits` - `SignerLimits` (see Types below)
|
|
160
|
+
- `store` - `SignerStore.Persistent` or `SignerStore.Temporary`
|
|
161
|
+
- `expiration` - Optional ledger expiration
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## PasskeyServer (Server)
|
|
166
|
+
|
|
167
|
+
Server-side utilities for Mercury indexing and OpenZeppelin Relayer.
|
|
168
|
+
|
|
169
|
+
### Constructor
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
const server = new PasskeyServer({
|
|
173
|
+
rpcUrl?: string,
|
|
174
|
+
relayerUrl?: string, // OpenZeppelin Relayer URL
|
|
175
|
+
relayerApiKey?: string, // Relayer API key
|
|
176
|
+
mercuryProjectName?: string, // Mercury project name
|
|
177
|
+
mercuryUrl?: string, // Mercury URL
|
|
178
|
+
mercuryJwt?: string, // Mercury JWT (use either JWT or Key)
|
|
179
|
+
mercuryKey?: string // Mercury API key
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Methods
|
|
184
|
+
|
|
185
|
+
#### `getSigners(contractId)`
|
|
186
|
+
Get all signers for a wallet from Mercury.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
const signers: Signer[] = await server.getSigners('C...')
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### `getContractId(options, index?)`
|
|
193
|
+
Reverse lookup a wallet address from a signer.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const contractId = await server.getContractId({
|
|
197
|
+
keyId?: string, // Passkey ID (Secp256r1)
|
|
198
|
+
publicKey?: string, // Ed25519 public key
|
|
199
|
+
policy?: string // Policy address
|
|
200
|
+
}, index) // If multiple wallets, select by index (default: 0)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### `send(txn)`
|
|
204
|
+
Submit a transaction via OpenZeppelin Relayer.
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
const result = await server.send(txn) // AssembledTransaction | Tx | string
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## SACClient
|
|
213
|
+
|
|
214
|
+
Helper for interacting with Stellar Asset Contracts.
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
const sac = new SACClient({
|
|
218
|
+
networkPassphrase: string,
|
|
219
|
+
rpcUrl: string
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
const tokenClient = sac.getSACClient('C...') // SAC contract ID
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Types
|
|
228
|
+
|
|
229
|
+
### SignerKey
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
SignerKey.Policy(contractAddress) // Policy signer
|
|
233
|
+
SignerKey.Ed25519(publicKey) // Ed25519 signer
|
|
234
|
+
SignerKey.Secp256r1(keyId) // Passkey signer
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### SignerLimits
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
type SignerLimits = Map<string, SignerKey[] | undefined> | undefined
|
|
241
|
+
|
|
242
|
+
// Example: Limit signer to specific contract, requires co-signer
|
|
243
|
+
const limits = new Map([
|
|
244
|
+
['C...contractAddress', [SignerKey.Ed25519('G...')]]
|
|
245
|
+
])
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### SignerStore
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
enum SignerStore {
|
|
252
|
+
Persistent = 'Persistent', // Permanent storage
|
|
253
|
+
Temporary = 'Temporary' // Expires, cheaper
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Signer
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
type Signer = {
|
|
261
|
+
kind: string // 'Secp256r1' | 'Ed25519' | 'Policy'
|
|
262
|
+
key: string // Signer identifier
|
|
263
|
+
val: string // Public key or empty
|
|
264
|
+
expiration: number | null
|
|
265
|
+
storage: 'Persistent' | 'Temporary'
|
|
266
|
+
limits: string // JSON stringified limits
|
|
267
|
+
evicted?: boolean // True if temporary signer was evicted
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Deploy the Mercury Indexer
|
|
274
|
+
|
|
275
|
+
To track signers and reverse lookup wallet addresses, deploy the Zephyr program:
|
|
44
276
|
|
|
45
277
|
```bash
|
|
46
278
|
cd ./zephyr
|
|
47
279
|
cargo install mercury-cli
|
|
48
|
-
# Get a JWT from
|
|
280
|
+
# Get a JWT from https://test.mercurydata.app
|
|
49
281
|
export MERCURY_JWT="<YOUR.MERCURY.JWT>"
|
|
50
|
-
#
|
|
282
|
+
# Requires Rust 1.79.0+
|
|
51
283
|
mercury-cli --jwt $MERCURY_JWT --local false --mainnet false deploy
|
|
52
284
|
```
|
|
53
285
|
|
|
54
|
-
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## TypeScript Configuration
|
|
55
289
|
|
|
56
|
-
This
|
|
290
|
+
This library exports TypeScript only to avoid bundling `@stellar/stellar-sdk` twice. Configure your bundler to transpile it.
|
|
57
291
|
|
|
58
|
-
|
|
292
|
+
**Next.js** (`next.config.mjs`):
|
|
59
293
|
```mjs
|
|
60
294
|
/** @type {import('next').NextConfig} */
|
|
61
295
|
const nextConfig = {
|
|
62
296
|
transpilePackages: [
|
|
63
|
-
'passkey-kit',
|
|
64
|
-
'passkey-factory-sdk',
|
|
297
|
+
'passkey-kit',
|
|
298
|
+
'passkey-factory-sdk',
|
|
65
299
|
'passkey-kit-sdk',
|
|
66
300
|
'sac-sdk',
|
|
67
301
|
]
|
|
68
|
-
}
|
|
302
|
+
}
|
|
69
303
|
|
|
70
|
-
export default nextConfig
|
|
304
|
+
export default nextConfig
|
|
71
305
|
```
|
|
72
|
-
If someone smarter than me knows how to include an optional JS build from a TS library please submit a PR. I just don't want to deploy a compiled version of this and wind up having folks doubling up on an already gargantuan dependency.
|
|
73
306
|
|
|
74
|
-
|
|
307
|
+
---
|
|
75
308
|
|
|
76
|
-
|
|
77
|
-
- `./src` - Contains the TypeScript files for the actual TS SDK library.
|
|
78
|
-
- `./demo` - Contains a basic demo of the SDK in action.
|
|
79
|
-
- `./contracts` - Contains the Rust Soroban smart contracts of the smart wallet implementation.
|
|
80
|
-
- `./zephyr` - Contains the [Zephyr](https://www.mercurydata.app/products/zephyr-vm) program for processing smart wallet events.
|
|
81
|
-
|
|
82
|
-
To install dependencies:
|
|
309
|
+
## Contributing
|
|
83
310
|
|
|
84
311
|
```bash
|
|
312
|
+
# Install dependencies
|
|
85
313
|
pnpm i
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
To build:
|
|
89
314
|
|
|
90
|
-
|
|
315
|
+
# Build
|
|
91
316
|
pnpm run build
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
To run the demo:
|
|
95
317
|
|
|
96
|
-
|
|
97
|
-
cd ./demo
|
|
98
|
-
pnpm i
|
|
99
|
-
pnpm run start
|
|
318
|
+
# Run demo
|
|
319
|
+
cd ./demo && pnpm i && pnpm run start
|
|
100
320
|
```
|
|
101
321
|
|
|
322
|
+
**Directory structure:**
|
|
323
|
+
- `./src` - TypeScript SDK source
|
|
324
|
+
- `./demo` - Demo application
|
|
325
|
+
- `./contracts` - Rust Soroban smart contracts
|
|
326
|
+
- `./zephyr` - Mercury Zephyr indexer program
|
|
327
|
+
|
|
102
328
|
> [!IMPORTANT]
|
|
103
|
-
> If
|
|
329
|
+
> If modifying contracts in `./contracts`, run the make commands. Update `SMART_WALLET_FACTORY` and `SMART_WALLET_WASM` values from `make deploy` before running `make init`.
|
|
104
330
|
|
|
105
331
|
> [!IMPORTANT]
|
|
106
|
-
>
|
|
332
|
+
> The bindings in `./packages` have been heavily modified. When rebuilding, prefer updating only the `src/index.ts` files in each package.
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## Resources
|
|
337
|
+
|
|
338
|
+
- [Super Peach](https://github.com/kalepail/superpeach) - Real-world implementation example
|
|
339
|
+
- [Discord #passkeys](https://discord.gg/stellardev) - Questions and showcase
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "passkey-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "A helper library for creating and using smart wallet accounts on the Stellar blockchain.",
|
|
5
5
|
"author": "Tyler van der Hoeven",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
"main": "src/index.ts",
|
|
9
9
|
"types": "types/index.d.ts",
|
|
10
10
|
"dependencies": {
|
|
11
|
+
"@openzeppelin/relayer-plugin-channels": "^0.5.0",
|
|
11
12
|
"@simplewebauthn/browser": "^13.2.0",
|
|
12
13
|
"@stellar/stellar-sdk": "^14.2.0",
|
|
13
14
|
"base64url": "^3.0.1",
|
|
14
15
|
"buffer": "^6.0.3",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
16
|
+
"passkey-kit-sdk": "0.7.2",
|
|
17
|
+
"sac-sdk": "0.4.2"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@types/node": "^24.6.0",
|
package/src/kit.ts
CHANGED
|
@@ -8,6 +8,9 @@ import { PasskeyBase } from './base'
|
|
|
8
8
|
import { AssembledTransaction, basicNodeSigner, type AssembledTransactionOptions, type Tx } from '@stellar/stellar-sdk/minimal/contract'
|
|
9
9
|
import type { Server } from '@stellar/stellar-sdk/minimal/rpc'
|
|
10
10
|
|
|
11
|
+
// TODO we should allow setting the rpId in the constructor so we don't have to keep setting it for every call
|
|
12
|
+
// e.g. if you want to sign with a smol.xyz key on next.smol.xyz key you have to set rpId over and over again
|
|
13
|
+
|
|
11
14
|
export class PasskeyKit extends PasskeyBase {
|
|
12
15
|
declare rpc: Server
|
|
13
16
|
declare rpcUrl: string
|
|
@@ -48,12 +51,19 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
48
51
|
this.walletKeypair = Keypair.fromRawEd25519Seed(hash(Buffer.from('kalepail')));
|
|
49
52
|
this.walletPublicKey = this.walletKeypair.publicKey()
|
|
50
53
|
this.walletWasmHash = walletWasmHash
|
|
51
|
-
this.timeoutInSeconds = options.timeoutInSeconds || 30 //
|
|
54
|
+
this.timeoutInSeconds = options.timeoutInSeconds || 30 // OpenZeppelin Relayer requires <= 30 second timeout so let's default to that
|
|
52
55
|
this.WebAuthn = WebAuthn || { startRegistration, startAuthentication }
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
public async createWallet(
|
|
56
|
-
|
|
58
|
+
public async createWallet(
|
|
59
|
+
app: string,
|
|
60
|
+
user: string,
|
|
61
|
+
settings?: {
|
|
62
|
+
rpId?: string
|
|
63
|
+
authenticatorSelection?: AuthenticatorSelectionCriteria
|
|
64
|
+
}
|
|
65
|
+
) {
|
|
66
|
+
const { rawResponse, keyId, keyIdBase64, publicKey } = await this.createKey(app, user, settings)
|
|
57
67
|
|
|
58
68
|
const at = await PasskeyClient.deploy(
|
|
59
69
|
{
|
package/src/server.ts
CHANGED
|
@@ -5,25 +5,22 @@ import type { Tx } from "@stellar/stellar-sdk/minimal/contract"
|
|
|
5
5
|
import type { Signer } from "./types"
|
|
6
6
|
import { AssembledTransaction } from "@stellar/stellar-sdk/minimal/contract"
|
|
7
7
|
import { Durability } from "@stellar/stellar-sdk/minimal/rpc"
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
// TODO set default headers in constructor
|
|
8
|
+
import { ChannelsClient } from "@openzeppelin/relayer-plugin-channels"
|
|
11
9
|
|
|
12
10
|
export class PasskeyServer extends PasskeyBase {
|
|
13
|
-
private
|
|
11
|
+
private relayerApiKey: string | undefined
|
|
14
12
|
private mercuryJwt: string | undefined
|
|
15
13
|
private mercuryKey: string | undefined
|
|
14
|
+
private channelsClient: ChannelsClient | undefined
|
|
16
15
|
|
|
17
|
-
public
|
|
18
|
-
public launchtubeHeaders: Record<string, string> | undefined
|
|
16
|
+
public relayerUrl: string | undefined
|
|
19
17
|
public mercuryProjectName: string | undefined
|
|
20
18
|
public mercuryUrl: string | undefined
|
|
21
19
|
|
|
22
20
|
constructor(options: {
|
|
23
21
|
rpcUrl?: string,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
launchtubeHeaders?: Record<string, string>
|
|
22
|
+
relayerUrl?: string,
|
|
23
|
+
relayerApiKey?: string,
|
|
27
24
|
mercuryProjectName?: string,
|
|
28
25
|
mercuryUrl?: string,
|
|
29
26
|
mercuryJwt?: string,
|
|
@@ -31,9 +28,8 @@ export class PasskeyServer extends PasskeyBase {
|
|
|
31
28
|
}) {
|
|
32
29
|
const {
|
|
33
30
|
rpcUrl,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
launchtubeHeaders,
|
|
31
|
+
relayerUrl,
|
|
32
|
+
relayerApiKey,
|
|
37
33
|
mercuryProjectName,
|
|
38
34
|
mercuryUrl,
|
|
39
35
|
mercuryJwt,
|
|
@@ -42,14 +38,18 @@ export class PasskeyServer extends PasskeyBase {
|
|
|
42
38
|
|
|
43
39
|
super(rpcUrl)
|
|
44
40
|
|
|
45
|
-
if (
|
|
46
|
-
this.
|
|
41
|
+
if (relayerUrl)
|
|
42
|
+
this.relayerUrl = relayerUrl
|
|
47
43
|
|
|
48
|
-
if (
|
|
49
|
-
this.
|
|
44
|
+
if (relayerApiKey)
|
|
45
|
+
this.relayerApiKey = relayerApiKey
|
|
50
46
|
|
|
51
|
-
if (
|
|
52
|
-
this.
|
|
47
|
+
if (relayerUrl && relayerApiKey) {
|
|
48
|
+
this.channelsClient = new ChannelsClient({
|
|
49
|
+
baseUrl: relayerUrl,
|
|
50
|
+
apiKey: relayerApiKey,
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
53
|
|
|
54
54
|
if (mercuryProjectName)
|
|
55
55
|
this.mercuryProjectName = mercuryProjectName
|
|
@@ -158,42 +158,22 @@ export class PasskeyServer extends PasskeyBase {
|
|
|
158
158
|
- Add a method for getting a paginated or filtered list of all a wallet's events
|
|
159
159
|
*/
|
|
160
160
|
|
|
161
|
-
public async send<T>(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
) {
|
|
165
|
-
if (!this.launchtubeUrl)
|
|
166
|
-
throw new Error('Launchtube service not configured')
|
|
161
|
+
public async send<T>(txn: AssembledTransaction<T> | Tx | string) {
|
|
162
|
+
if (!this.channelsClient)
|
|
163
|
+
throw new Error('Relayer service not configured')
|
|
167
164
|
|
|
168
|
-
|
|
165
|
+
let txnXdr: string
|
|
169
166
|
|
|
170
167
|
if (txn instanceof AssembledTransaction) {
|
|
171
|
-
|
|
168
|
+
txnXdr = txn.built!.toXDR()
|
|
172
169
|
} else if (typeof txn !== 'string') {
|
|
173
|
-
|
|
170
|
+
txnXdr = txn.toXDR()
|
|
171
|
+
} else {
|
|
172
|
+
txnXdr = txn
|
|
174
173
|
}
|
|
175
174
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (fee)
|
|
179
|
-
data.set('fee', fee.toString());
|
|
180
|
-
|
|
181
|
-
let lt_headers = Object.assign({
|
|
182
|
-
'X-Client-Name': 'passkey-kit',
|
|
183
|
-
'X-Client-Version': version,
|
|
184
|
-
}, this.launchtubeHeaders)
|
|
185
|
-
|
|
186
|
-
if (this.launchtubeJwt)
|
|
187
|
-
lt_headers.authorization = `Bearer ${this.launchtubeJwt}`
|
|
188
|
-
|
|
189
|
-
return fetch(this.launchtubeUrl, {
|
|
190
|
-
method: 'POST',
|
|
191
|
-
headers: lt_headers,
|
|
192
|
-
body: data
|
|
193
|
-
}).then(async (res) => {
|
|
194
|
-
if (res.ok)
|
|
195
|
-
return res.json()
|
|
196
|
-
else throw await res.json()
|
|
175
|
+
return this.channelsClient.submitTransaction({
|
|
176
|
+
xdr: txnXdr,
|
|
197
177
|
})
|
|
198
178
|
}
|
|
199
|
-
}
|
|
179
|
+
}
|
package/types/kit.d.ts
CHANGED
|
@@ -27,7 +27,10 @@ export declare class PasskeyKit extends PasskeyBase {
|
|
|
27
27
|
startAuthentication: typeof startAuthentication;
|
|
28
28
|
};
|
|
29
29
|
});
|
|
30
|
-
createWallet(app: string, user: string
|
|
30
|
+
createWallet(app: string, user: string, settings?: {
|
|
31
|
+
rpId?: string;
|
|
32
|
+
authenticatorSelection?: AuthenticatorSelectionCriteria;
|
|
33
|
+
}): Promise<{
|
|
31
34
|
rawResponse: import("@simplewebauthn/browser").RegistrationResponseJSON;
|
|
32
35
|
keyId: Buffer<ArrayBufferLike>;
|
|
33
36
|
keyIdBase64: string;
|
package/types/server.d.ts
CHANGED
|
@@ -3,18 +3,17 @@ import type { Tx } from "@stellar/stellar-sdk/minimal/contract";
|
|
|
3
3
|
import type { Signer } from "./types";
|
|
4
4
|
import { AssembledTransaction } from "@stellar/stellar-sdk/minimal/contract";
|
|
5
5
|
export declare class PasskeyServer extends PasskeyBase {
|
|
6
|
-
private
|
|
6
|
+
private relayerApiKey;
|
|
7
7
|
private mercuryJwt;
|
|
8
8
|
private mercuryKey;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
private channelsClient;
|
|
10
|
+
relayerUrl: string | undefined;
|
|
11
11
|
mercuryProjectName: string | undefined;
|
|
12
12
|
mercuryUrl: string | undefined;
|
|
13
13
|
constructor(options: {
|
|
14
14
|
rpcUrl?: string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
launchtubeHeaders?: Record<string, string>;
|
|
15
|
+
relayerUrl?: string;
|
|
16
|
+
relayerApiKey?: string;
|
|
18
17
|
mercuryProjectName?: string;
|
|
19
18
|
mercuryUrl?: string;
|
|
20
19
|
mercuryJwt?: string;
|
|
@@ -26,5 +25,5 @@ export declare class PasskeyServer extends PasskeyBase {
|
|
|
26
25
|
publicKey?: string;
|
|
27
26
|
policy?: string;
|
|
28
27
|
}, index?: number): Promise<string>;
|
|
29
|
-
send<T>(txn: AssembledTransaction<T> | Tx | string
|
|
28
|
+
send<T>(txn: AssembledTransaction<T> | Tx | string): Promise<import("@openzeppelin/relayer-plugin-channels").ChannelsTransactionResponse>;
|
|
30
29
|
}
|