passkey-kit 0.2.4 → 0.3.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/.github/workflows/release.yml +31 -0
- package/.vscode/settings.json +2 -0
- package/README.md +52 -6
- package/TODO.md +1 -0
- package/cheatsheet +11 -1
- package/package.json +5 -5
- package/packages/passkey-factory-sdk/package.json +1 -1
- package/packages/passkey-factory-sdk/src/index.ts +5 -75
- package/packages/passkey-factory-sdk/types/index.d.ts +1 -70
- package/packages/passkey-kit-sdk/package.json +1 -1
- package/packages/passkey-kit-sdk/src/index.ts +12 -34
- package/packages/passkey-kit-sdk/types/index.d.ts +9 -28
- package/src/kit.ts +61 -72
- package/tsconfig.json +1 -1
- package/types/kit.d.ts +14 -10
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Contract Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
release_name:
|
|
7
|
+
description: 'Unique release name'
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
|
|
13
|
+
release-contract-webauthn-factory:
|
|
14
|
+
uses: stellar-expert/soroban-build-workflow/.github/workflows/release.yml@main
|
|
15
|
+
with:
|
|
16
|
+
release_name: ${{ github.ref_name }}
|
|
17
|
+
release_description: 'Release of the factory contract'
|
|
18
|
+
relative_path: 'contracts'
|
|
19
|
+
package: 'webauthn-factory'
|
|
20
|
+
secrets:
|
|
21
|
+
release_token: ${{ secrets.GITHUB_TOKEN }}
|
|
22
|
+
|
|
23
|
+
release-contract-webauthn-secp256r1:
|
|
24
|
+
uses: stellar-expert/soroban-build-workflow/.github/workflows/release.yml@main
|
|
25
|
+
with:
|
|
26
|
+
release_name: ${{ github.ref_name }}
|
|
27
|
+
release_description: 'Release of the secp256r1 contract'
|
|
28
|
+
relative_path: 'contracts'
|
|
29
|
+
package: 'webauthn-secp256r1'
|
|
30
|
+
secrets:
|
|
31
|
+
release_token: ${{ secrets.GITHUB_TOKEN }}
|
package/.vscode/settings.json
CHANGED
package/README.md
CHANGED
|
@@ -1,4 +1,44 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Passkey Kit
|
|
2
|
+
|
|
3
|
+
Passkey kit is a basic TypeScript SDK for creating and managing Stellar smart wallets. It's intended to be used in tandem with [Launchtube](https://github.com/kalepail/launchtube) for submitting passkey signed transactions onchain however this is not a requirement. This is both a client and a server side library. `PasskeyKit` on the client and `PasskeyBase` on the server.
|
|
4
|
+
|
|
5
|
+
Demo site: [passkey-kit-demo.pages.dev](https://passkey-kit-demo.pages.dev/)
|
|
6
|
+
|
|
7
|
+
To get started first install the package:
|
|
8
|
+
```
|
|
9
|
+
pnpm i passkey-kit
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
On the client:
|
|
13
|
+
```ts
|
|
14
|
+
const account = new PasskeyKit({
|
|
15
|
+
rpcUrl: env.RPC_URL,
|
|
16
|
+
networkPassphrase: env.NETWORK_PASSPHRASE
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
On the server:
|
|
21
|
+
```ts
|
|
22
|
+
const account = new PasskeyKit({
|
|
23
|
+
launchtubeUrl: env.LAUNCHTUBE_URL,
|
|
24
|
+
launchtubeJwt: env.LAUNCHTUBE_JWT,
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Note that while I don't recommend it you can use the server-intended `send` method on the client side by passing in the `launchtubeUrl` and `launchtubeJwt` values to the `PasskeyKit` constructor. We do this in the `./demo` site to ease demonstration, development and experimentation, however in a production environment you'll want to keep your secrets safe on the server.
|
|
29
|
+
|
|
30
|
+
This is a fully typed library so docs aren't provided, however there's a full example showcasing all the core public methods in the `./demo` directory. I also recommend reviewing the [Super Peach](https://github.com/kalepail/superpeach) repo for an example of how you could implement both the client and server side in a more real-world scenario.
|
|
31
|
+
|
|
32
|
+
Good luck, have fun, and change the world!
|
|
33
|
+
|
|
34
|
+
For any questions or to showcase your progress please join the `#passkeys` channel on our [Discord](https://discord.gg/stellardev).
|
|
35
|
+
|
|
36
|
+
## Contributing
|
|
37
|
+
|
|
38
|
+
Passkey kit consists of three primary directories:
|
|
39
|
+
- `./contracts` - Contains the Rust Soroban smart contracts of the smart wallet implementation.
|
|
40
|
+
- `./src` - Contains the TypeScript files for the actual TS SDK library.
|
|
41
|
+
- `./demo` - Contains a basic demo of the SDK in action.
|
|
2
42
|
|
|
3
43
|
To install dependencies:
|
|
4
44
|
|
|
@@ -12,10 +52,16 @@ To build:
|
|
|
12
52
|
pnpm run build
|
|
13
53
|
```
|
|
14
54
|
|
|
15
|
-
|
|
55
|
+
To run the demo:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
cd ./demo
|
|
59
|
+
pnpm i
|
|
60
|
+
pnpm run start
|
|
61
|
+
```
|
|
16
62
|
|
|
17
|
-
|
|
63
|
+
> [!IMPORTANT]
|
|
64
|
+
> If you fiddle with contracts in `./contracts` you'll need to run the make commands. Just remember to update the `WEBAUTHN_FACTORY` and `WEBAUTHN_WASM` values from the `make deploy` command before running `make init`.
|
|
18
65
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- [ ] Attach some meaningful metadata to signers so you know which one belongs to which domain
|
|
66
|
+
> [!IMPORTANT]
|
|
67
|
+
> Keep in mind the bindings here in `./packages` have been _heavily_ modified. Be careful when rebuilding and updating. Likely you'll only want to update the `src/index.ts` files in each respective package vs swapping out entire directories.
|
package/TODO.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- [ ] Add timestamps to zephyr event data
|
package/cheatsheet
CHANGED
|
@@ -2,4 +2,14 @@
|
|
|
2
2
|
npm publish --workspaces
|
|
3
3
|
|
|
4
4
|
# Install passkey-kit
|
|
5
|
-
pnpm publish --no-git-checks
|
|
5
|
+
pnpm publish --no-git-checks
|
|
6
|
+
|
|
7
|
+
# Mercury commands
|
|
8
|
+
# https://test.mercurydata.app/
|
|
9
|
+
|
|
10
|
+
export MERCURY_JWT=???
|
|
11
|
+
mercury-cli --jwt $MERCURY_JWT --local false --mainnet false deploy
|
|
12
|
+
mercury-cli --jwt $MERCURY_JWT --local false --mainnet false catchup --contracts "???" # don't forget to subscribe to the contract first
|
|
13
|
+
curl -X POST https://api.mercurydata.app/zephyr/execute -H "Authorization: Bearer $MERCURY_JWT" -H 'Content-Type: application/json' -d '{"mode":{"Function": {"fname": "get_signers_by_address", "arguments": "{\"address\": \"CBLWEW63G2KU7ZGVQTTFTJLGQSXAU5PU5ZXERQDDLL4LBA72D7ER6C75\"}"}}}'
|
|
14
|
+
curl -X POST https://api.mercurydata.app/zephyr/execute -H "Authorization: Bearer $MERCURY_JWT" -H 'Content-Type: application/json' -d '{"mode":{"Function": {"fname": "get_address_by_signer", "arguments": "{\"id\": [78,127,30,69,248,174,95,168,47,59,161,168,51,120,117,135,112,133,232,92]}"}}}'
|
|
15
|
+
curl -X POST https://api.mercurydata.app/zephyr/execute -H "Authorization: Bearer $MERCURY_JWT" -H 'Content-Type: application/json' -d '{"mode":{"Function": {"fname": "get_events_by_address", "arguments": "{\"address\": \"CBLWEW63G2KU7ZGVQTTFTJLGQSXAU5PU5ZXERQDDLL4LBA72D7ER6C75\"}"}}}'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "passkey-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A helper library for creating and using passkey accounts on the Stellar blockchain.",
|
|
5
5
|
"author": "Tyler van der Hoeven",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
"types": "types/index.d.ts",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@simplewebauthn/browser": "^10.0.0",
|
|
12
|
-
"@stellar/stellar-sdk": "12.0
|
|
12
|
+
"@stellar/stellar-sdk": "12.1.0",
|
|
13
13
|
"base64url": "^3.0.1",
|
|
14
14
|
"bigint-conversion": "^2.4.3",
|
|
15
15
|
"buffer": "^6.0.3",
|
|
16
16
|
"cbor-x": "^1.5.9",
|
|
17
|
-
"passkey-
|
|
18
|
-
"passkey-
|
|
17
|
+
"passkey-factory-sdk": "0.1.0",
|
|
18
|
+
"passkey-kit-sdk": "0.1.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"typescript": "^5.
|
|
21
|
+
"typescript": "^5.5.3"
|
|
22
22
|
},
|
|
23
23
|
"workspaces": [
|
|
24
24
|
"packages/*"
|
|
@@ -15,39 +15,16 @@ if (typeof window !== 'undefined') {
|
|
|
15
15
|
export const networks = {
|
|
16
16
|
testnet: {
|
|
17
17
|
networkPassphrase: "Test SDF Network ; September 2015",
|
|
18
|
-
contractId: "
|
|
18
|
+
contractId: "CA6DVSXLLOSI32JAPGP4MLOG64FGERLYCP2SGRX2A6MPWGA5KDUKL66P",
|
|
19
19
|
}
|
|
20
20
|
} as const
|
|
21
21
|
|
|
22
22
|
export const Errors = {
|
|
23
23
|
1: { message: "" },
|
|
24
|
-
2: { message: "" }
|
|
25
|
-
3: { message: "" },
|
|
26
|
-
4: { message: "" },
|
|
27
|
-
5: { message: "" }
|
|
24
|
+
2: { message: "" }
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
export interface Client {
|
|
31
|
-
/**
|
|
32
|
-
* Construct and simulate a extend_ttl transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
33
|
-
*/
|
|
34
|
-
extend_ttl: (options?: {
|
|
35
|
-
/**
|
|
36
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
37
|
-
*/
|
|
38
|
-
fee?: number;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
42
|
-
*/
|
|
43
|
-
timeoutInSeconds?: number;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
47
|
-
*/
|
|
48
|
-
simulate?: boolean;
|
|
49
|
-
}) => Promise<AssembledTransaction<null>>
|
|
50
|
-
|
|
51
28
|
/**
|
|
52
29
|
* Construct and simulate a init transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
53
30
|
*/
|
|
@@ -87,65 +64,18 @@ export interface Client {
|
|
|
87
64
|
*/
|
|
88
65
|
simulate?: boolean;
|
|
89
66
|
}) => Promise<AssembledTransaction<Result<string>>>
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Construct and simulate a add_sig transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
93
|
-
*/
|
|
94
|
-
add_sig: ({ id, contract }: { id: Buffer, contract: string }, options?: {
|
|
95
|
-
/**
|
|
96
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
97
|
-
*/
|
|
98
|
-
fee?: number;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
102
|
-
*/
|
|
103
|
-
timeoutInSeconds?: number;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
107
|
-
*/
|
|
108
|
-
simulate?: boolean;
|
|
109
|
-
}) => Promise<AssembledTransaction<Result<void>>>
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Construct and simulate a rm_sig transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
113
|
-
*/
|
|
114
|
-
rm_sig: ({ id, contract }: { id: Buffer, contract: string }, options?: {
|
|
115
|
-
/**
|
|
116
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
117
|
-
*/
|
|
118
|
-
fee?: number;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
122
|
-
*/
|
|
123
|
-
timeoutInSeconds?: number;
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
127
|
-
*/
|
|
128
|
-
simulate?: boolean;
|
|
129
|
-
}) => Promise<AssembledTransaction<Result<void>>>
|
|
130
|
-
|
|
131
67
|
}
|
|
132
68
|
export class Client extends ContractClient {
|
|
133
69
|
constructor(public readonly options: ContractClientOptions) {
|
|
134
70
|
super(
|
|
135
|
-
new ContractSpec(["
|
|
136
|
-
"AAAAAAAAAAAAAAAKZXh0ZW5kX3R0bAAAAAAAAAAAAAA=",
|
|
71
|
+
new ContractSpec(["AAAABAAAAAAAAAAAAAAABUVycm9yAAAAAAAAAgAAAAAAAAAOTm90SW5pdGlhbGl6ZWQAAAAAAAEAAAAAAAAAEkFscmVhZHlJbml0aWFsaXplZAAAAAAAAg==",
|
|
137
72
|
"AAAAAAAAAAAAAAAEaW5pdAAAAAEAAAAAAAAACXdhc21faGFzaAAAAAAAA+4AAAAgAAAAAQAAA+kAAAPtAAAAAAAAAAM=",
|
|
138
|
-
"AAAAAAAAAAAAAAAGZGVwbG95AAAAAAACAAAAAAAAAAJpZAAAAAAADgAAAAAAAAACcGsAAAAAA+4AAABBAAAAAQAAA+kAAAATAAAAAw==",
|
|
139
|
-
"AAAAAAAAAAAAAAAHYWRkX3NpZwAAAAACAAAAAAAAAAJpZAAAAAAADgAAAAAAAAAIY29udHJhY3QAAAATAAAAAQAAA+kAAAPtAAAAAAAAAAM=",
|
|
140
|
-
"AAAAAAAAAAAAAAAGcm1fc2lnAAAAAAACAAAAAAAAAAJpZAAAAAAADgAAAAAAAAAIY29udHJhY3QAAAATAAAAAQAAA+kAAAPtAAAAAAAAAAM="]),
|
|
73
|
+
"AAAAAAAAAAAAAAAGZGVwbG95AAAAAAACAAAAAAAAAAJpZAAAAAAADgAAAAAAAAACcGsAAAAAA+4AAABBAAAAAQAAA+kAAAATAAAAAw=="]),
|
|
141
74
|
options
|
|
142
75
|
)
|
|
143
76
|
}
|
|
144
77
|
public readonly fromJSON = {
|
|
145
|
-
extend_ttl: this.txFromJSON<null>,
|
|
146
78
|
init: this.txFromJSON<Result<void>>,
|
|
147
|
-
deploy: this.txFromJSON<Result<string
|
|
148
|
-
add_sig: this.txFromJSON<Result<void>>,
|
|
149
|
-
rm_sig: this.txFromJSON<Result<void>>
|
|
79
|
+
deploy: this.txFromJSON<Result<string>>
|
|
150
80
|
}
|
|
151
81
|
}
|
|
@@ -3,7 +3,7 @@ import { AssembledTransaction, Client as ContractClient, ClientOptions as Contra
|
|
|
3
3
|
export declare const networks: {
|
|
4
4
|
readonly testnet: {
|
|
5
5
|
readonly networkPassphrase: "Test SDF Network ; September 2015";
|
|
6
|
-
readonly contractId: "
|
|
6
|
+
readonly contractId: "CA6DVSXLLOSI32JAPGP4MLOG64FGERLYCP2SGRX2A6MPWGA5KDUKL66P";
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
9
|
export declare const Errors: {
|
|
@@ -13,34 +13,8 @@ export declare const Errors: {
|
|
|
13
13
|
2: {
|
|
14
14
|
message: string;
|
|
15
15
|
};
|
|
16
|
-
3: {
|
|
17
|
-
message: string;
|
|
18
|
-
};
|
|
19
|
-
4: {
|
|
20
|
-
message: string;
|
|
21
|
-
};
|
|
22
|
-
5: {
|
|
23
|
-
message: string;
|
|
24
|
-
};
|
|
25
16
|
};
|
|
26
17
|
export interface Client {
|
|
27
|
-
/**
|
|
28
|
-
* Construct and simulate a extend_ttl transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
29
|
-
*/
|
|
30
|
-
extend_ttl: (options?: {
|
|
31
|
-
/**
|
|
32
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
33
|
-
*/
|
|
34
|
-
fee?: number;
|
|
35
|
-
/**
|
|
36
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
37
|
-
*/
|
|
38
|
-
timeoutInSeconds?: number;
|
|
39
|
-
/**
|
|
40
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
41
|
-
*/
|
|
42
|
-
simulate?: boolean;
|
|
43
|
-
}) => Promise<AssembledTransaction<null>>;
|
|
44
18
|
/**
|
|
45
19
|
* Construct and simulate a init transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
46
20
|
*/
|
|
@@ -80,55 +54,12 @@ export interface Client {
|
|
|
80
54
|
*/
|
|
81
55
|
simulate?: boolean;
|
|
82
56
|
}) => Promise<AssembledTransaction<Result<string>>>;
|
|
83
|
-
/**
|
|
84
|
-
* Construct and simulate a add_sig transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
85
|
-
*/
|
|
86
|
-
add_sig: ({ id, contract }: {
|
|
87
|
-
id: Buffer;
|
|
88
|
-
contract: string;
|
|
89
|
-
}, options?: {
|
|
90
|
-
/**
|
|
91
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
92
|
-
*/
|
|
93
|
-
fee?: number;
|
|
94
|
-
/**
|
|
95
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
96
|
-
*/
|
|
97
|
-
timeoutInSeconds?: number;
|
|
98
|
-
/**
|
|
99
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
100
|
-
*/
|
|
101
|
-
simulate?: boolean;
|
|
102
|
-
}) => Promise<AssembledTransaction<Result<void>>>;
|
|
103
|
-
/**
|
|
104
|
-
* Construct and simulate a rm_sig transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
105
|
-
*/
|
|
106
|
-
rm_sig: ({ id, contract }: {
|
|
107
|
-
id: Buffer;
|
|
108
|
-
contract: string;
|
|
109
|
-
}, options?: {
|
|
110
|
-
/**
|
|
111
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
112
|
-
*/
|
|
113
|
-
fee?: number;
|
|
114
|
-
/**
|
|
115
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
116
|
-
*/
|
|
117
|
-
timeoutInSeconds?: number;
|
|
118
|
-
/**
|
|
119
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
120
|
-
*/
|
|
121
|
-
simulate?: boolean;
|
|
122
|
-
}) => Promise<AssembledTransaction<Result<void>>>;
|
|
123
57
|
}
|
|
124
58
|
export declare class Client extends ContractClient {
|
|
125
59
|
readonly options: ContractClientOptions;
|
|
126
60
|
constructor(options: ContractClientOptions);
|
|
127
61
|
readonly fromJSON: {
|
|
128
|
-
extend_ttl: (json: string) => AssembledTransaction<null>;
|
|
129
62
|
init: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
130
63
|
deploy: (json: string) => AssembledTransaction<Result<string, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
131
|
-
add_sig: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
132
|
-
rm_sig: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
133
64
|
};
|
|
134
65
|
}
|
|
@@ -15,7 +15,7 @@ if (typeof window !== 'undefined') {
|
|
|
15
15
|
export const networks = {
|
|
16
16
|
testnet: {
|
|
17
17
|
networkPassphrase: "Test SDF Network ; September 2015",
|
|
18
|
-
contractId: "
|
|
18
|
+
contractId: "CA6DVSXLLOSI32JAPGP4MLOG64FGERLYCP2SGRX2A6MPWGA5KDUKL66P",
|
|
19
19
|
}
|
|
20
20
|
} as const
|
|
21
21
|
|
|
@@ -40,30 +40,10 @@ export interface Signature {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export interface Client {
|
|
43
|
-
/**
|
|
44
|
-
* Construct and simulate a extend_ttl transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
45
|
-
*/
|
|
46
|
-
extend_ttl: (options?: {
|
|
47
|
-
/**
|
|
48
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
49
|
-
*/
|
|
50
|
-
fee?: number;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
54
|
-
*/
|
|
55
|
-
timeoutInSeconds?: number;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
59
|
-
*/
|
|
60
|
-
simulate?: boolean;
|
|
61
|
-
}) => Promise<AssembledTransaction<null>>
|
|
62
|
-
|
|
63
43
|
/**
|
|
64
44
|
* Construct and simulate a init transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
65
45
|
*/
|
|
66
|
-
init: ({ id, pk
|
|
46
|
+
init: ({ id, pk }: { id: Buffer, pk: Buffer }, options?: {
|
|
67
47
|
/**
|
|
68
48
|
* The fee to pay for the transaction. Default: BASE_FEE
|
|
69
49
|
*/
|
|
@@ -101,9 +81,9 @@ export interface Client {
|
|
|
101
81
|
}) => Promise<AssembledTransaction<Result<void>>>
|
|
102
82
|
|
|
103
83
|
/**
|
|
104
|
-
* Construct and simulate a
|
|
84
|
+
* Construct and simulate a add_sig transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
105
85
|
*/
|
|
106
|
-
|
|
86
|
+
add_sig: ({ id, pk }: { id: Buffer, pk: Buffer }, options?: {
|
|
107
87
|
/**
|
|
108
88
|
* The fee to pay for the transaction. Default: BASE_FEE
|
|
109
89
|
*/
|
|
@@ -141,9 +121,9 @@ export interface Client {
|
|
|
141
121
|
}) => Promise<AssembledTransaction<Result<void>>>
|
|
142
122
|
|
|
143
123
|
/**
|
|
144
|
-
* Construct and simulate a
|
|
124
|
+
* Construct and simulate a re_super transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
145
125
|
*/
|
|
146
|
-
|
|
126
|
+
re_super: ({ id }: { id: Buffer }, options?: {
|
|
147
127
|
/**
|
|
148
128
|
* The fee to pay for the transaction. Default: BASE_FEE
|
|
149
129
|
*/
|
|
@@ -163,24 +143,22 @@ export interface Client {
|
|
|
163
143
|
export class Client extends ContractClient {
|
|
164
144
|
constructor(public readonly options: ContractClientOptions) {
|
|
165
145
|
super(
|
|
166
|
-
new ContractSpec(["
|
|
167
|
-
"
|
|
168
|
-
"AAAAAAAAAAAAAAAEaW5pdAAAAAMAAAAAAAAAAmlkAAAAAAAOAAAAAAAAAAJwawAAAAAD7gAAAEEAAAAAAAAAB2ZhY3RvcnkAAAAAEwAAAAEAAAPpAAAD7QAAAAAAAAAD",
|
|
146
|
+
new ContractSpec(["AAAABAAAAAAAAAAAAAAABUVycm9yAAAAAAAACgAAAAAAAAAOTm90SW5pdGlhbGl6ZWQAAAAAAAEAAAAAAAAACE5vdEZvdW5kAAAAAgAAAAAAAAAMTm90UGVybWl0dGVkAAAAAwAAAAAAAAASQWxyZWFkeUluaXRpYWxpemVkAAAAAAAEAAAAAAAAAA5Kc29uUGFyc2VFcnJvcgAAAAAABQAAAAAAAAAOSW52YWxpZENvbnRleHQAAAAAAAYAAAAAAAAAIENsaWVudERhdGFKc29uQ2hhbGxlbmdlSW5jb3JyZWN0AAAABwAAAAAAAAAXU2VjcDI1NnIxUHVibGljS2V5UGFyc2UAAAAACAAAAAAAAAAXU2VjcDI1NnIxU2lnbmF0dXJlUGFyc2UAAAAACQAAAAAAAAAVU2VjcDI1NnIxVmVyaWZ5RmFpbGVkAAAAAAAACg==",
|
|
147
|
+
"AAAAAAAAAAAAAAAEaW5pdAAAAAIAAAAAAAAAAmlkAAAAAAAOAAAAAAAAAAJwawAAAAAD7gAAAEEAAAABAAAD6QAAA+0AAAAAAAAAAw==",
|
|
169
148
|
"AAAAAAAAAAAAAAAHdXBncmFkZQAAAAABAAAAAAAAAARoYXNoAAAD7gAAACAAAAABAAAD6QAAA+0AAAAAAAAAAw==",
|
|
170
|
-
"AAAAAAAAAAAAAAAGcmVzdWRvAAAAAAABAAAAAAAAAAJpZAAAAAAADgAAAAEAAAPpAAAD7QAAAAAAAAAD",
|
|
171
|
-
"AAAAAAAAAAAAAAAGcm1fc2lnAAAAAAABAAAAAAAAAAJpZAAAAAAADgAAAAEAAAPpAAAD7QAAAAAAAAAD",
|
|
172
149
|
"AAAAAAAAAAAAAAAHYWRkX3NpZwAAAAACAAAAAAAAAAJpZAAAAAAADgAAAAAAAAACcGsAAAAAA+4AAABBAAAAAQAAA+kAAAPtAAAAAAAAAAM=",
|
|
150
|
+
"AAAAAAAAAAAAAAAGcm1fc2lnAAAAAAABAAAAAAAAAAJpZAAAAAAADgAAAAEAAAPpAAAD7QAAAAAAAAAD",
|
|
151
|
+
"AAAAAAAAAAAAAAAIcmVfc3VwZXIAAAABAAAAAAAAAAJpZAAAAAAADgAAAAEAAAPpAAAD7QAAAAAAAAAD",
|
|
173
152
|
"AAAAAQAAAAAAAAAAAAAACVNpZ25hdHVyZQAAAAAAAAQAAAAAAAAAEmF1dGhlbnRpY2F0b3JfZGF0YQAAAAAADgAAAAAAAAAQY2xpZW50X2RhdGFfanNvbgAAAA4AAAAAAAAAAmlkAAAAAAAOAAAAAAAAAAlzaWduYXR1cmUAAAAAAAPuAAAAQA==",
|
|
174
153
|
"AAAAAAAAAAAAAAAMX19jaGVja19hdXRoAAAAAwAAAAAAAAARc2lnbmF0dXJlX3BheWxvYWQAAAAAAAPuAAAAIAAAAAAAAAAJc2lnbmF0dXJlAAAAAAAH0AAAAAlTaWduYXR1cmUAAAAAAAAAAAAADWF1dGhfY29udGV4dHMAAAAAAAPqAAAH0AAAAAdDb250ZXh0AAAAAAEAAAPpAAAD7QAAAAAAAAAD"]),
|
|
175
154
|
options
|
|
176
155
|
)
|
|
177
156
|
}
|
|
178
157
|
public readonly fromJSON = {
|
|
179
|
-
extend_ttl: this.txFromJSON<null>,
|
|
180
158
|
init: this.txFromJSON<Result<void>>,
|
|
181
159
|
upgrade: this.txFromJSON<Result<void>>,
|
|
182
|
-
resudo: this.txFromJSON<Result<void>>,
|
|
183
|
-
rm_sig: this.txFromJSON<Result<void>>,
|
|
184
160
|
add_sig: this.txFromJSON<Result<void>>,
|
|
161
|
+
rm_sig: this.txFromJSON<Result<void>>,
|
|
162
|
+
re_super: this.txFromJSON<Result<void>>
|
|
185
163
|
}
|
|
186
164
|
}
|
|
@@ -3,7 +3,7 @@ import { AssembledTransaction, Client as ContractClient, ClientOptions as Contra
|
|
|
3
3
|
export declare const networks: {
|
|
4
4
|
readonly testnet: {
|
|
5
5
|
readonly networkPassphrase: "Test SDF Network ; September 2015";
|
|
6
|
-
readonly contractId: "
|
|
6
|
+
readonly contractId: "CA6DVSXLLOSI32JAPGP4MLOG64FGERLYCP2SGRX2A6MPWGA5KDUKL66P";
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
9
|
export declare const Errors: {
|
|
@@ -45,30 +45,12 @@ export interface Signature {
|
|
|
45
45
|
signature: Buffer;
|
|
46
46
|
}
|
|
47
47
|
export interface Client {
|
|
48
|
-
/**
|
|
49
|
-
* Construct and simulate a extend_ttl transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
50
|
-
*/
|
|
51
|
-
extend_ttl: (options?: {
|
|
52
|
-
/**
|
|
53
|
-
* The fee to pay for the transaction. Default: BASE_FEE
|
|
54
|
-
*/
|
|
55
|
-
fee?: number;
|
|
56
|
-
/**
|
|
57
|
-
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
|
|
58
|
-
*/
|
|
59
|
-
timeoutInSeconds?: number;
|
|
60
|
-
/**
|
|
61
|
-
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
|
|
62
|
-
*/
|
|
63
|
-
simulate?: boolean;
|
|
64
|
-
}) => Promise<AssembledTransaction<null>>;
|
|
65
48
|
/**
|
|
66
49
|
* Construct and simulate a init transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
67
50
|
*/
|
|
68
|
-
init: ({ id, pk
|
|
51
|
+
init: ({ id, pk }: {
|
|
69
52
|
id: Buffer;
|
|
70
53
|
pk: Buffer;
|
|
71
|
-
factory: string;
|
|
72
54
|
}, options?: {
|
|
73
55
|
/**
|
|
74
56
|
* The fee to pay for the transaction. Default: BASE_FEE
|
|
@@ -103,10 +85,11 @@ export interface Client {
|
|
|
103
85
|
simulate?: boolean;
|
|
104
86
|
}) => Promise<AssembledTransaction<Result<void>>>;
|
|
105
87
|
/**
|
|
106
|
-
* Construct and simulate a
|
|
88
|
+
* Construct and simulate a add_sig transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
107
89
|
*/
|
|
108
|
-
|
|
90
|
+
add_sig: ({ id, pk }: {
|
|
109
91
|
id: Buffer;
|
|
92
|
+
pk: Buffer;
|
|
110
93
|
}, options?: {
|
|
111
94
|
/**
|
|
112
95
|
* The fee to pay for the transaction. Default: BASE_FEE
|
|
@@ -141,11 +124,10 @@ export interface Client {
|
|
|
141
124
|
simulate?: boolean;
|
|
142
125
|
}) => Promise<AssembledTransaction<Result<void>>>;
|
|
143
126
|
/**
|
|
144
|
-
* Construct and simulate a
|
|
127
|
+
* Construct and simulate a re_super transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
|
|
145
128
|
*/
|
|
146
|
-
|
|
129
|
+
re_super: ({ id }: {
|
|
147
130
|
id: Buffer;
|
|
148
|
-
pk: Buffer;
|
|
149
131
|
}, options?: {
|
|
150
132
|
/**
|
|
151
133
|
* The fee to pay for the transaction. Default: BASE_FEE
|
|
@@ -165,11 +147,10 @@ export declare class Client extends ContractClient {
|
|
|
165
147
|
readonly options: ContractClientOptions;
|
|
166
148
|
constructor(options: ContractClientOptions);
|
|
167
149
|
readonly fromJSON: {
|
|
168
|
-
extend_ttl: (json: string) => AssembledTransaction<null>;
|
|
169
150
|
init: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
170
151
|
upgrade: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
171
|
-
resudo: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
172
|
-
rm_sig: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
173
152
|
add_sig: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
153
|
+
rm_sig: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
154
|
+
re_super: (json: string) => AssembledTransaction<Result<void, import("@stellar/stellar-sdk/contract").ErrorMessage>>;
|
|
174
155
|
};
|
|
175
156
|
}
|
package/src/kit.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Client as PasskeyClient } from 'passkey-kit-sdk'
|
|
2
|
-
import { Client as FactoryClient
|
|
2
|
+
import { Client as FactoryClient } from 'passkey-factory-sdk'
|
|
3
3
|
import { Address, Networks, StrKey, hash, xdr, Transaction, SorobanRpc, Operation, scValToNative, TransactionBuilder } from '@stellar/stellar-sdk'
|
|
4
4
|
import { bufToBigint, bigintToBuf } from 'bigint-conversion'
|
|
5
5
|
import base64url from 'base64url'
|
|
@@ -8,44 +8,30 @@ import { decode } from 'cbor-x/decode'
|
|
|
8
8
|
import { Buffer } from 'buffer'
|
|
9
9
|
import { PasskeyBase } from './base'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- Clean up these params and the interface as a whole
|
|
13
|
-
Might put wallet activities and maybe factory as well into the root of the class vs buried inside this.wallet and this.factory
|
|
14
|
-
@Later
|
|
15
|
-
- Right now publicKey can mean a Stellar public key or a passkey public key, there should be a noted difference
|
|
16
|
-
*/
|
|
11
|
+
type GetContractIdFunction = (keyId: string) => Promise<string>;
|
|
17
12
|
|
|
18
13
|
export class PasskeyKit extends PasskeyBase {
|
|
19
14
|
public keyId: string | undefined
|
|
20
|
-
public
|
|
15
|
+
public keyExpired: boolean | undefined
|
|
21
16
|
public wallet: PasskeyClient | undefined
|
|
22
17
|
public factory: FactoryClient
|
|
23
18
|
public networkPassphrase: Networks
|
|
24
19
|
public rpcUrl: string
|
|
25
20
|
public rpc: SorobanRpc.Server
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/* NOTE
|
|
29
|
-
- Consider adding the ability to pass in a keyId and maybe even a contractId in order to preconnect to a wallet
|
|
30
|
-
If just a keyId call `connectWallet` in order to get the contractId
|
|
31
|
-
If both keyId and contractId are passed in then we can skip the connectWallet call (though we won't get the sudoKeyId in that case)
|
|
32
|
-
We don't strictly _need_ this as a dev can just call `connectWallet` after class instantiation but it might be a nice convenience
|
|
33
|
-
`connectWallet` is async making it tricky to know when the wallet is "ready". Thus I think it's better for `connectWallet` to be called externally
|
|
34
|
-
@No
|
|
35
|
-
*/
|
|
21
|
+
|
|
36
22
|
constructor(options: {
|
|
37
23
|
rpcUrl: string,
|
|
38
24
|
launchtubeUrl?: string,
|
|
39
25
|
launchtubeJwt?: string,
|
|
40
|
-
|
|
41
|
-
|
|
26
|
+
networkPassphrase: string,
|
|
27
|
+
factoryContractId: string,
|
|
42
28
|
}) {
|
|
43
29
|
const {
|
|
44
30
|
rpcUrl,
|
|
45
31
|
launchtubeUrl,
|
|
46
32
|
launchtubeJwt,
|
|
47
|
-
factoryContractId,
|
|
48
33
|
networkPassphrase,
|
|
34
|
+
factoryContractId,
|
|
49
35
|
} = options
|
|
50
36
|
|
|
51
37
|
super({
|
|
@@ -53,14 +39,11 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
53
39
|
launchtubeJwt,
|
|
54
40
|
})
|
|
55
41
|
|
|
56
|
-
if (factoryContractId)
|
|
57
|
-
this.factoryContractId = factoryContractId
|
|
58
|
-
|
|
59
42
|
this.rpcUrl = rpcUrl
|
|
60
43
|
this.rpc = new SorobanRpc.Server(rpcUrl)
|
|
61
|
-
this.networkPassphrase = networkPassphrase
|
|
44
|
+
this.networkPassphrase = networkPassphrase as Networks
|
|
62
45
|
this.factory = new FactoryClient({
|
|
63
|
-
contractId:
|
|
46
|
+
contractId: factoryContractId,
|
|
64
47
|
networkPassphrase,
|
|
65
48
|
rpcUrl
|
|
66
49
|
})
|
|
@@ -110,14 +93,9 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
110
93
|
attestation: "none",
|
|
111
94
|
});
|
|
112
95
|
|
|
113
|
-
if (!this.keyId)
|
|
96
|
+
if (!this.keyId)
|
|
114
97
|
this.keyId = startRegistrationResponse.id
|
|
115
98
|
|
|
116
|
-
// If there was no keyId we're likely about to deploy a new wallet so we should set the sudoKeyId
|
|
117
|
-
if (!this.sudoKeyId)
|
|
118
|
-
this.sudoKeyId = startRegistrationResponse.id
|
|
119
|
-
}
|
|
120
|
-
|
|
121
99
|
const { publicKeyObject } = this.getPublicKeyObject(startRegistrationResponse.response.attestationObject);
|
|
122
100
|
|
|
123
101
|
const publicKey = Buffer.from([
|
|
@@ -132,7 +110,13 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
132
110
|
}
|
|
133
111
|
}
|
|
134
112
|
|
|
135
|
-
public async connectWallet(
|
|
113
|
+
public async connectWallet(opts: {
|
|
114
|
+
keyId?: string | Uint8Array,
|
|
115
|
+
getContractId?: GetContractIdFunction
|
|
116
|
+
}) {
|
|
117
|
+
let { keyId, getContractId } = opts
|
|
118
|
+
let keyIdBuffer: Uint8Array
|
|
119
|
+
|
|
136
120
|
if (!keyId) {
|
|
137
121
|
const { id } = await startAuthentication({
|
|
138
122
|
challenge: base64url("stellaristhebetterblockchain"),
|
|
@@ -143,45 +127,59 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
143
127
|
keyId = id
|
|
144
128
|
}
|
|
145
129
|
|
|
130
|
+
if (keyId instanceof Uint8Array) {
|
|
131
|
+
keyIdBuffer = keyId
|
|
132
|
+
keyId = base64url(keyId)
|
|
133
|
+
} else {
|
|
134
|
+
keyIdBuffer = base64url.toBuffer(keyId)
|
|
135
|
+
}
|
|
136
|
+
|
|
146
137
|
if (!this.keyId)
|
|
147
138
|
this.keyId = keyId
|
|
148
139
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
// NOTE might not need this for derivation as all signers are stored in the factory and we can use that lookup as both primary and secondary
|
|
152
|
-
let contractId = StrKey.encodeContract(hash(xdr.HashIdPreimage.envelopeTypeContractId(
|
|
140
|
+
// Check for the contractId on-chain as a derivation from the keyId. This is the easiest and "cheapest" check however it will only work for the initially deployed passkey if it was used as derivation
|
|
141
|
+
let contractId: string | undefined = StrKey.encodeContract(hash(xdr.HashIdPreimage.envelopeTypeContractId(
|
|
153
142
|
new xdr.HashIdPreimageContractId({
|
|
154
143
|
networkId: hash(Buffer.from(this.networkPassphrase, 'utf-8')),
|
|
155
144
|
contractIdPreimage: xdr.ContractIdPreimage.contractIdPreimageFromAddress(
|
|
156
145
|
new xdr.ContractIdPreimageFromAddress({
|
|
157
|
-
address: Address.fromString(this.
|
|
146
|
+
address: Address.fromString(this.factory.options.contractId).toScAddress(),
|
|
158
147
|
salt: hash(keyIdBuffer),
|
|
159
148
|
})
|
|
160
149
|
)
|
|
161
150
|
})
|
|
162
151
|
).toXDR()));
|
|
163
152
|
|
|
164
|
-
let contractData: SorobanRpc.Api.LedgerEntryResult | undefined
|
|
165
|
-
|
|
166
153
|
// attempt passkey id derivation
|
|
167
154
|
try {
|
|
168
|
-
|
|
155
|
+
await this.rpc.getContractData(contractId, xdr.ScVal.scvLedgerKeyContractInstance())
|
|
169
156
|
}
|
|
170
157
|
// if that fails look up from the factory mapper
|
|
171
158
|
catch {
|
|
172
|
-
|
|
173
|
-
|
|
159
|
+
contractId = undefined
|
|
160
|
+
|
|
161
|
+
if (getContractId) {
|
|
162
|
+
contractId = await getContractId(keyId)
|
|
163
|
+
|
|
164
|
+
// Handle case where temporary session signer is missing on-chain (so we can queue up a re-add)
|
|
165
|
+
try {
|
|
166
|
+
await this.rpc.getContractData(contractId, xdr.ScVal.scvBytes(keyIdBuffer), SorobanRpc.Durability.Temporary)
|
|
167
|
+
// throw true
|
|
168
|
+
} catch {
|
|
169
|
+
this.keyExpired = true
|
|
170
|
+
}
|
|
171
|
+
}
|
|
174
172
|
}
|
|
175
173
|
|
|
174
|
+
if (!contractId)
|
|
175
|
+
throw new Error('No `contractId` was found')
|
|
176
|
+
|
|
176
177
|
this.wallet = new PasskeyClient({
|
|
177
178
|
contractId,
|
|
178
179
|
networkPassphrase: this.networkPassphrase,
|
|
179
180
|
rpcUrl: this.rpcUrl
|
|
180
181
|
})
|
|
181
182
|
|
|
182
|
-
// get and set the sudo signer (passing in `contractData` from the `getContractData` call above to avoid dupe requests)
|
|
183
|
-
await this.getData(contractData)
|
|
184
|
-
|
|
185
183
|
return {
|
|
186
184
|
keyId: keyIdBuffer,
|
|
187
185
|
contractId
|
|
@@ -191,7 +189,7 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
191
189
|
public async signAuthEntry(
|
|
192
190
|
entry: xdr.SorobanAuthorizationEntry,
|
|
193
191
|
options?: {
|
|
194
|
-
keyId?: 'any' |
|
|
192
|
+
keyId?: 'any' | string | Uint8Array
|
|
195
193
|
ledgersToLive?: number
|
|
196
194
|
}
|
|
197
195
|
) {
|
|
@@ -212,7 +210,6 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
212
210
|
|
|
213
211
|
const authenticationResponse = await startAuthentication(
|
|
214
212
|
keyId === 'any'
|
|
215
|
-
|| (keyId === 'sudo' && !this.sudoKeyId)
|
|
216
213
|
|| (!keyId && !this.keyId)
|
|
217
214
|
? {
|
|
218
215
|
challenge: base64url(payload),
|
|
@@ -224,11 +221,9 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
224
221
|
// rpId: undefined,
|
|
225
222
|
allowCredentials: [
|
|
226
223
|
{
|
|
227
|
-
id: keyId
|
|
228
|
-
?
|
|
229
|
-
: keyId
|
|
230
|
-
? base64url(keyId)
|
|
231
|
-
: keyId || this.keyId!,
|
|
224
|
+
id: keyId instanceof Uint8Array
|
|
225
|
+
? base64url(keyId)
|
|
226
|
+
: keyId || this.keyId!,
|
|
232
227
|
type: "public-key",
|
|
233
228
|
},
|
|
234
229
|
],
|
|
@@ -238,7 +233,7 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
238
233
|
|
|
239
234
|
const signatureRaw = base64url.toBuffer(authenticationResponse.response.signature);
|
|
240
235
|
const signature = this.convertEcdsaSignatureAsnToCompact(signatureRaw);
|
|
241
|
-
|
|
236
|
+
|
|
242
237
|
credentials.signatureExpirationLedger(lastLedger + ledgersToLive)
|
|
243
238
|
credentials.signature(xdr.ScVal.scvMap([
|
|
244
239
|
new xdr.ScMapEntry({
|
|
@@ -258,13 +253,13 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
258
253
|
val: xdr.ScVal.scvBytes(signature),
|
|
259
254
|
}),
|
|
260
255
|
]))
|
|
261
|
-
|
|
256
|
+
|
|
262
257
|
return entry
|
|
263
258
|
}
|
|
264
259
|
public async signAuthEntries(
|
|
265
260
|
entries: xdr.SorobanAuthorizationEntry[],
|
|
266
261
|
options?: {
|
|
267
|
-
keyId?: 'any' |
|
|
262
|
+
keyId?: 'any' | string | Uint8Array
|
|
268
263
|
ledgersToLive?: number
|
|
269
264
|
}
|
|
270
265
|
) {
|
|
@@ -281,21 +276,18 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
281
276
|
|
|
282
277
|
return entries
|
|
283
278
|
}
|
|
284
|
-
/* NOTE
|
|
285
|
-
- Is there anything to be done with using the TS bindings `signAuthEntries` logic? Likely not but worth exploring
|
|
286
|
-
Perhaps not but maybe the js-sdk's `authorizeEntry` or `authorizeInvocation`
|
|
287
|
-
https://stellar.github.io/js-stellar-sdk/global.html#authorizeInvocation
|
|
288
|
-
These methods all only support ed25519 Keypairs
|
|
289
|
-
@No
|
|
290
|
-
*/
|
|
291
279
|
public async sign(
|
|
292
280
|
txn: Transaction | string,
|
|
293
281
|
options?: {
|
|
294
|
-
keyId?: 'any' |
|
|
282
|
+
keyId?: 'any' | string | Uint8Array
|
|
295
283
|
ledgersToLive?: number
|
|
296
284
|
}
|
|
297
285
|
) {
|
|
298
|
-
|
|
286
|
+
/*
|
|
287
|
+
- Hack to ensure we don't stack fees when simulating and assembling multiple times
|
|
288
|
+
AssembleTransaction always adds the resource fee onto the transaction fee.
|
|
289
|
+
This is bad in cases where you need to simulate multiple times
|
|
290
|
+
*/
|
|
299
291
|
txn = TransactionBuilder.cloneFrom(new Transaction(
|
|
300
292
|
typeof txn === 'string'
|
|
301
293
|
? txn
|
|
@@ -311,7 +303,7 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
311
303
|
op.type !== 'invokeHostFunction'
|
|
312
304
|
&& op.type !== 'extendFootprintTtl'
|
|
313
305
|
&& op.type !== 'restoreFootprint'
|
|
314
|
-
) throw new Error('Must include only one operation of type `invokeHostFunction` or `extendFootprintTtl` or `restoreFootprint`')
|
|
306
|
+
) throw new Error('Must include only one operation of type `invokeHostFunction` or `extendFootprintTtl` or `restoreFootprint`')
|
|
315
307
|
}
|
|
316
308
|
|
|
317
309
|
// Only need to sign auth for `invokeHostFunction` operations
|
|
@@ -331,11 +323,10 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
331
323
|
|
|
332
324
|
return SorobanRpc.assembleTransaction(txn, sim).build().toXDR()
|
|
333
325
|
}
|
|
334
|
-
|
|
335
|
-
public async getData(contractData?: SorobanRpc.Api.LedgerEntryResult) {
|
|
326
|
+
public async getSuperKeyId() {
|
|
336
327
|
const data: Map<string, any> = new Map()
|
|
337
328
|
|
|
338
|
-
const { val } =
|
|
329
|
+
const { val } = await this.rpc.getContractData(
|
|
339
330
|
this.wallet!.options.contractId,
|
|
340
331
|
xdr.ScVal.scvLedgerKeyContractInstance(),
|
|
341
332
|
);
|
|
@@ -351,9 +342,7 @@ export class PasskeyKit extends PasskeyBase {
|
|
|
351
342
|
);
|
|
352
343
|
});
|
|
353
344
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
return data
|
|
345
|
+
return base64url(data.get('super'))
|
|
357
346
|
}
|
|
358
347
|
|
|
359
348
|
/* TODO
|
package/tsconfig.json
CHANGED
package/types/kit.d.ts
CHANGED
|
@@ -3,21 +3,21 @@ import { Client as FactoryClient } from 'passkey-factory-sdk';
|
|
|
3
3
|
import { Networks, xdr, Transaction, SorobanRpc } from '@stellar/stellar-sdk';
|
|
4
4
|
import { Buffer } from 'buffer';
|
|
5
5
|
import { PasskeyBase } from './base';
|
|
6
|
+
type GetContractIdFunction = (keyId: string) => Promise<string>;
|
|
6
7
|
export declare class PasskeyKit extends PasskeyBase {
|
|
7
8
|
keyId: string | undefined;
|
|
8
|
-
|
|
9
|
+
keyExpired: boolean | undefined;
|
|
9
10
|
wallet: PasskeyClient | undefined;
|
|
10
11
|
factory: FactoryClient;
|
|
11
12
|
networkPassphrase: Networks;
|
|
12
13
|
rpcUrl: string;
|
|
13
14
|
rpc: SorobanRpc.Server;
|
|
14
|
-
factoryContractId: string;
|
|
15
15
|
constructor(options: {
|
|
16
16
|
rpcUrl: string;
|
|
17
17
|
launchtubeUrl?: string;
|
|
18
18
|
launchtubeJwt?: string;
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
networkPassphrase: string;
|
|
20
|
+
factoryContractId: string;
|
|
21
21
|
});
|
|
22
22
|
createWallet(name: string, user: string): Promise<{
|
|
23
23
|
keyId: Buffer;
|
|
@@ -28,23 +28,27 @@ export declare class PasskeyKit extends PasskeyBase {
|
|
|
28
28
|
keyId: Buffer;
|
|
29
29
|
publicKey: Buffer;
|
|
30
30
|
}>;
|
|
31
|
-
connectWallet(
|
|
32
|
-
keyId
|
|
31
|
+
connectWallet(opts: {
|
|
32
|
+
keyId?: string | Uint8Array;
|
|
33
|
+
getContractId?: GetContractIdFunction;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
keyId: Uint8Array;
|
|
33
36
|
contractId: string;
|
|
34
37
|
}>;
|
|
35
38
|
signAuthEntry(entry: xdr.SorobanAuthorizationEntry, options?: {
|
|
36
|
-
keyId?: 'any' |
|
|
39
|
+
keyId?: 'any' | string | Uint8Array;
|
|
37
40
|
ledgersToLive?: number;
|
|
38
41
|
}): Promise<xdr.SorobanAuthorizationEntry>;
|
|
39
42
|
signAuthEntries(entries: xdr.SorobanAuthorizationEntry[], options?: {
|
|
40
|
-
keyId?: 'any' |
|
|
43
|
+
keyId?: 'any' | string | Uint8Array;
|
|
41
44
|
ledgersToLive?: number;
|
|
42
45
|
}): Promise<xdr.SorobanAuthorizationEntry[]>;
|
|
43
46
|
sign(txn: Transaction | string, options?: {
|
|
44
|
-
keyId?: 'any' |
|
|
47
|
+
keyId?: 'any' | string | Uint8Array;
|
|
45
48
|
ledgersToLive?: number;
|
|
46
49
|
}): Promise<string>;
|
|
47
|
-
|
|
50
|
+
getSuperKeyId(): Promise<string>;
|
|
48
51
|
private getPublicKeyObject;
|
|
49
52
|
private convertEcdsaSignatureAsnToCompact;
|
|
50
53
|
}
|
|
54
|
+
export {};
|