@solana/keychain-dfns 0.0.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +136 -0
- package/dist/__tests__/dfns-signer.integration.test.d.ts +2 -0
- package/dist/__tests__/dfns-signer.integration.test.d.ts.map +1 -0
- package/dist/__tests__/dfns-signer.integration.test.js +17 -0
- package/dist/__tests__/dfns-signer.integration.test.js.map +1 -0
- package/dist/__tests__/dfns-signer.test.d.ts +2 -0
- package/dist/__tests__/dfns-signer.test.d.ts.map +1 -0
- package/dist/__tests__/dfns-signer.test.js +157 -0
- package/dist/__tests__/dfns-signer.test.js.map +1 -0
- package/dist/__tests__/setup.d.ts +45 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +64 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/auth.d.ts +7 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +117 -0
- package/dist/auth.js.map +1 -0
- package/dist/dfns-signer.d.ts +65 -0
- package/dist/dfns-signer.d.ts.map +1 -0
- package/dist/dfns-signer.js +331 -0
- package/dist/dfns-signer.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -8
- package/src/__tests__/dfns-signer.integration.test.ts +17 -0
- package/src/__tests__/dfns-signer.test.ts +217 -0
- package/src/__tests__/setup.ts +76 -0
- package/src/auth.ts +136 -0
- package/src/dfns-signer.ts +421 -0
- package/src/index.ts +2 -0
- package/src/types.ts +113 -0
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# @solana/keychain-dfns
|
|
2
|
+
|
|
3
|
+
Dfns-based signer for Solana transactions using [Dfns](https://dfns.co) Keys API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @solana/keychain-dfns
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
1. A [Dfns](https://dfns.co) account with API access
|
|
14
|
+
2. A Solana wallet created in the Dfns dashboard
|
|
15
|
+
3. A service account with signing permissions
|
|
16
|
+
|
|
17
|
+
### Setting Up a Service Account
|
|
18
|
+
|
|
19
|
+
Follow the [Creating a Service
|
|
20
|
+
Account](https://docs.dfns.co/guides/developers/creating-a-service-account) guide:
|
|
21
|
+
|
|
22
|
+
1. **Generate a keypair** - https://docs.dfns.co/guides/developers/generate-a-key-pair#generate-a-key-pair
|
|
23
|
+
2. **Create the service account** in Settings > Developers > Service Accounts, pasting your public key
|
|
24
|
+
3. **Save the auth token** — it is only shown once. Store it securely along with your private key
|
|
25
|
+
4. **Configure permissions** — assign a role with minimal required permissions
|
|
26
|
+
|
|
27
|
+
You will need:
|
|
28
|
+
- **Auth token** (`authToken`) — the service account token
|
|
29
|
+
- **Credential ID** (`credId`) — shown in the service account details
|
|
30
|
+
- **Private key** (`privateKeyPem`) — the PEM key you generated in step 1
|
|
31
|
+
- **Wallet ID** (`walletId`) — found in the Dfns dashboard under Wallets
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
### Basic Setup
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { createDfnsSigner } from '@solana/keychain-dfns';
|
|
39
|
+
|
|
40
|
+
const signer = await createDfnsSigner({
|
|
41
|
+
authToken: 'your-service-account-token',
|
|
42
|
+
credId: 'your-credential-id',
|
|
43
|
+
privateKeyPem: `-----BEGIN PRIVATE KEY-----
|
|
44
|
+
...your private key...
|
|
45
|
+
-----END PRIVATE KEY-----`,
|
|
46
|
+
walletId: 'wa-xxxxx-xxxxx-xxxxx',
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log('Signer address:', signer.address);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Signing Transactions
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import {
|
|
56
|
+
appendTransactionMessageInstructions,
|
|
57
|
+
createSolanaRpc,
|
|
58
|
+
createTransactionMessage,
|
|
59
|
+
getBase64EncodedWireTransaction,
|
|
60
|
+
pipe,
|
|
61
|
+
setTransactionMessageFeePayerSigner,
|
|
62
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
63
|
+
signTransactionMessageWithSigners,
|
|
64
|
+
} from '@solana/kit';
|
|
65
|
+
|
|
66
|
+
const rpc = createSolanaRpc('https://api.devnet.solana.com');
|
|
67
|
+
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
68
|
+
|
|
69
|
+
const message = pipe(
|
|
70
|
+
createTransactionMessage({ version: 0 }),
|
|
71
|
+
(tx) => setTransactionMessageFeePayerSigner(signer, tx),
|
|
72
|
+
(tx) => appendTransactionMessageInstructions([/* your instructions */], tx),
|
|
73
|
+
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const signedTx = await signTransactionMessageWithSigners(message);
|
|
77
|
+
const encoded = getBase64EncodedWireTransaction(signedTx);
|
|
78
|
+
await rpc.sendTransaction(encoded).send();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Signing Messages
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const message = new TextEncoder().encode('Hello, Solana!');
|
|
85
|
+
const [signatureDictionary] = await signer.signMessages([{ content: message }]);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
### DfnsSignerConfig
|
|
91
|
+
|
|
92
|
+
| Field | Type | Required | Default | Description |
|
|
93
|
+
|-----------------|----------|----------|-------------------------|---------------------------------------------------|
|
|
94
|
+
| `authToken` | `string` | Yes | - | Service account token or personal access token |
|
|
95
|
+
| `credId` | `string` | Yes | - | Credential ID for user action signing |
|
|
96
|
+
| `privateKeyPem` | `string` | Yes | - | Private key in PEM format |
|
|
97
|
+
| `walletId` | `string` | Yes | - | Dfns wallet ID (starts with `wa-`) |
|
|
98
|
+
| `apiBaseUrl` | `string` | No | `https://api.dfns.io` | Custom API base URL |
|
|
99
|
+
| `requestDelayMs`| `number` | No | `0` | Delay in ms between concurrent signing requests |
|
|
100
|
+
|
|
101
|
+
## How It Works
|
|
102
|
+
|
|
103
|
+
1. **Initialization**: `create()` fetches the wallet from Dfns API and validates the Ed25519 public key
|
|
104
|
+
(your Solana address)
|
|
105
|
+
2. **Signing**: Transactions and messages are sent to the Dfns Keys API (`/keys/{keyId}/signatures`)
|
|
106
|
+
which returns Ed25519 signature components (r, s)
|
|
107
|
+
3. **User Action Signing**: Mutating API requests (like signing) go through a 3-step challenge/response
|
|
108
|
+
flow — the SDK handles this automatically using your `credId` and `privateKeyPem`
|
|
109
|
+
|
|
110
|
+
## Error Handling
|
|
111
|
+
|
|
112
|
+
The signer throws errors with specific codes from `@solana/keychain-core`:
|
|
113
|
+
|
|
114
|
+
- `CONFIG_ERROR` — Invalid configuration (missing fields, inactive wallet, unsupported key type)
|
|
115
|
+
- `REMOTE_API_ERROR` — Dfns API returned an error
|
|
116
|
+
- `SIGNING_FAILED` — Signature request failed or requires policy approval
|
|
117
|
+
- `PARSING_ERROR` — Failed to parse Dfns response
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { SignerErrorCode } from '@solana/keychain-core';
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
await signer.signMessages([message]);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (error.code === SignerErrorCode.REMOTE_API_ERROR) {
|
|
126
|
+
console.error('Dfns API error:', error.message);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Security Considerations
|
|
132
|
+
|
|
133
|
+
1. **Token Security**: Never hardcode auth tokens. Use environment variables or a secrets manager.
|
|
134
|
+
2. **Private Key**: Store the PEM private key securely. It is used to sign every user action requests.
|
|
135
|
+
3. **Policy Engine**: Configure [Dfns Policies](https://docs.dfns.co/api-reference/policies) to enforce
|
|
136
|
+
signing rules and approval workflows.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dfns-signer.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/dfns-signer.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, it } from 'vitest';
|
|
2
|
+
import { runSignerIntegrationTest } from '@solana/keychain-test-utils';
|
|
3
|
+
import { getConfig } from './setup';
|
|
4
|
+
import { config } from 'dotenv';
|
|
5
|
+
config();
|
|
6
|
+
describe('DfnsSigner Integration', () => {
|
|
7
|
+
it.skipIf(!process.env.DFNS_AUTH_TOKEN)('signs transactions with real API', async () => {
|
|
8
|
+
await runSignerIntegrationTest(await getConfig(['signTransaction']));
|
|
9
|
+
});
|
|
10
|
+
it.skipIf(!process.env.DFNS_AUTH_TOKEN)('signs messages with real API', async () => {
|
|
11
|
+
await runSignerIntegrationTest(await getConfig(['signMessage']));
|
|
12
|
+
});
|
|
13
|
+
it.skipIf(!process.env.DFNS_AUTH_TOKEN)('simulates transactions with real API', async () => {
|
|
14
|
+
await runSignerIntegrationTest(await getConfig(['simulateTransaction']));
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=dfns-signer.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dfns-signer.integration.test.js","sourceRoot":"","sources":["../../src/__tests__/dfns-signer.integration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,MAAM,EAAE,CAAC;AAET,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,wBAAwB,CAAC,MAAM,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,wBAAwB,CAAC,MAAM,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,wBAAwB,CAAC,MAAM,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dfns-signer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/dfns-signer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
vi.mock('@solana/keychain-core', async (importOriginal) => {
|
|
3
|
+
const mod = await importOriginal();
|
|
4
|
+
return { ...mod, assertSignatureValid: vi.fn() };
|
|
5
|
+
});
|
|
6
|
+
import { DfnsSigner } from '../dfns-signer.js';
|
|
7
|
+
import { TEST_AUTH_TOKEN, TEST_CRED_ID, TEST_ED25519_PEM, TEST_WALLET_ID, createSignatureResponse, createUserActionInitResponse, createUserActionResponse, createWalletResponse, } from './setup.js';
|
|
8
|
+
global.fetch = vi.fn();
|
|
9
|
+
const mockFetch = global.fetch;
|
|
10
|
+
const defaultConfig = {
|
|
11
|
+
authToken: TEST_AUTH_TOKEN,
|
|
12
|
+
credId: TEST_CRED_ID,
|
|
13
|
+
privateKeyPem: TEST_ED25519_PEM,
|
|
14
|
+
walletId: TEST_WALLET_ID,
|
|
15
|
+
};
|
|
16
|
+
function mockWalletFetch(overrides) {
|
|
17
|
+
mockFetch.mockResolvedValueOnce({
|
|
18
|
+
json: async () => createWalletResponse(overrides),
|
|
19
|
+
ok: true,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
describe('DfnsSigner', () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vi.resetAllMocks();
|
|
25
|
+
});
|
|
26
|
+
describe('create', () => {
|
|
27
|
+
it('creates a DfnsSigner with valid config', async () => {
|
|
28
|
+
mockWalletFetch();
|
|
29
|
+
const signer = await DfnsSigner.create(defaultConfig);
|
|
30
|
+
expect(signer).toBeDefined();
|
|
31
|
+
expect(signer.address).toBeDefined();
|
|
32
|
+
});
|
|
33
|
+
it('throws error for missing authToken', async () => {
|
|
34
|
+
await expect(DfnsSigner.create({ ...defaultConfig, authToken: '' })).rejects.toThrow('Missing required authToken field');
|
|
35
|
+
});
|
|
36
|
+
it('throws error for missing credId', async () => {
|
|
37
|
+
await expect(DfnsSigner.create({ ...defaultConfig, credId: '' })).rejects.toThrow('Missing required credId field');
|
|
38
|
+
});
|
|
39
|
+
it('throws error for missing privateKeyPem', async () => {
|
|
40
|
+
await expect(DfnsSigner.create({ ...defaultConfig, privateKeyPem: '' })).rejects.toThrow('Missing required privateKeyPem field');
|
|
41
|
+
});
|
|
42
|
+
it('throws error for missing walletId', async () => {
|
|
43
|
+
await expect(DfnsSigner.create({ ...defaultConfig, walletId: '' })).rejects.toThrow('Missing required walletId field');
|
|
44
|
+
});
|
|
45
|
+
it('throws error for inactive wallet', async () => {
|
|
46
|
+
mockWalletFetch({ status: 'Inactive' });
|
|
47
|
+
await expect(DfnsSigner.create(defaultConfig)).rejects.toThrow('not active');
|
|
48
|
+
});
|
|
49
|
+
it('throws error for non-EdDSA scheme', async () => {
|
|
50
|
+
mockWalletFetch({ scheme: 'ECDSA' });
|
|
51
|
+
await expect(DfnsSigner.create(defaultConfig)).rejects.toThrow('Unsupported key scheme');
|
|
52
|
+
});
|
|
53
|
+
it('throws error for API failure', async () => {
|
|
54
|
+
mockFetch.mockResolvedValueOnce({
|
|
55
|
+
ok: false,
|
|
56
|
+
status: 401,
|
|
57
|
+
});
|
|
58
|
+
await expect(DfnsSigner.create(defaultConfig)).rejects.toThrow();
|
|
59
|
+
});
|
|
60
|
+
it('throws error for negative requestDelayMs', async () => {
|
|
61
|
+
await expect(DfnsSigner.create({ ...defaultConfig, requestDelayMs: -1 })).rejects.toThrow('requestDelayMs must not be negative');
|
|
62
|
+
});
|
|
63
|
+
it('warns for high requestDelayMs', async () => {
|
|
64
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
65
|
+
mockWalletFetch();
|
|
66
|
+
await DfnsSigner.create({ ...defaultConfig, requestDelayMs: 5000 });
|
|
67
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('requestDelayMs is greater than 3000ms'));
|
|
68
|
+
warnSpy.mockRestore();
|
|
69
|
+
});
|
|
70
|
+
it('throws HTTP_ERROR when fetch fails during create', async () => {
|
|
71
|
+
mockFetch.mockRejectedValueOnce(new Error('Network timeout'));
|
|
72
|
+
await expect(DfnsSigner.create(defaultConfig)).rejects.toMatchObject({
|
|
73
|
+
code: 'SIGNER_HTTP_ERROR',
|
|
74
|
+
message: expect.stringContaining('Dfns network request failed'),
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('signMessages', () => {
|
|
79
|
+
it('throws HTTP_ERROR when fetch fails during signing', async () => {
|
|
80
|
+
mockWalletFetch();
|
|
81
|
+
const signer = await DfnsSigner.create(defaultConfig);
|
|
82
|
+
// The auth flow init request fails with network error
|
|
83
|
+
mockFetch.mockRejectedValueOnce(new Error('Network timeout'));
|
|
84
|
+
await expect(signer.signMessages([{ content: new Uint8Array([1, 2, 3]), signatures: {} }])).rejects.toMatchObject({
|
|
85
|
+
code: 'SIGNER_HTTP_ERROR',
|
|
86
|
+
message: expect.stringContaining('Dfns network request failed'),
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
it('signs a message successfully', async () => {
|
|
90
|
+
const rHex = '11'.repeat(32);
|
|
91
|
+
const sHex = '22'.repeat(32);
|
|
92
|
+
mockWalletFetch();
|
|
93
|
+
mockFetch.mockResolvedValueOnce({
|
|
94
|
+
json: async () => createUserActionInitResponse(),
|
|
95
|
+
ok: true,
|
|
96
|
+
});
|
|
97
|
+
mockFetch.mockResolvedValueOnce({
|
|
98
|
+
json: async () => createUserActionResponse(),
|
|
99
|
+
ok: true,
|
|
100
|
+
});
|
|
101
|
+
mockFetch.mockResolvedValueOnce({
|
|
102
|
+
json: async () => createSignatureResponse(rHex, sHex),
|
|
103
|
+
ok: true,
|
|
104
|
+
});
|
|
105
|
+
const signer = await DfnsSigner.create(defaultConfig);
|
|
106
|
+
const result = await signer.signMessages([{ content: new Uint8Array([1, 2, 3]), signatures: {} }]);
|
|
107
|
+
expect(result).toHaveLength(1);
|
|
108
|
+
expect(result[0]?.[signer.address]).toBeDefined();
|
|
109
|
+
const sig = result[0][signer.address];
|
|
110
|
+
expect(sig.length).toBe(64);
|
|
111
|
+
});
|
|
112
|
+
it('left-pads short signature components', async () => {
|
|
113
|
+
// r is 31 bytes (short by 1), s is 32 bytes
|
|
114
|
+
const rHex = 'ff'.repeat(31);
|
|
115
|
+
const sHex = 'aa'.repeat(32);
|
|
116
|
+
mockWalletFetch();
|
|
117
|
+
mockFetch.mockResolvedValueOnce({
|
|
118
|
+
json: async () => createUserActionInitResponse(),
|
|
119
|
+
ok: true,
|
|
120
|
+
});
|
|
121
|
+
mockFetch.mockResolvedValueOnce({
|
|
122
|
+
json: async () => createUserActionResponse(),
|
|
123
|
+
ok: true,
|
|
124
|
+
});
|
|
125
|
+
mockFetch.mockResolvedValueOnce({
|
|
126
|
+
json: async () => createSignatureResponse(rHex, sHex),
|
|
127
|
+
ok: true,
|
|
128
|
+
});
|
|
129
|
+
const signer = await DfnsSigner.create(defaultConfig);
|
|
130
|
+
const result = await signer.signMessages([{ content: new Uint8Array([1, 2, 3]), signatures: {} }]);
|
|
131
|
+
const sig = result[0][signer.address];
|
|
132
|
+
expect(sig.length).toBe(64);
|
|
133
|
+
// First byte should be 0x00 (left-pad), then 31 bytes of 0xff
|
|
134
|
+
expect(sig[0]).toBe(0x00);
|
|
135
|
+
expect(sig[1]).toBe(0xff);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
describe('isAvailable', () => {
|
|
139
|
+
it('returns true when API responds', async () => {
|
|
140
|
+
mockWalletFetch();
|
|
141
|
+
// isAvailable doesn't need create(), but we need a signer instance
|
|
142
|
+
mockWalletFetch(); // for the isAvailable call
|
|
143
|
+
const signer = await DfnsSigner.create(defaultConfig);
|
|
144
|
+
expect(await signer.isAvailable()).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
it('returns false when API fails', async () => {
|
|
147
|
+
mockWalletFetch(); // for create()
|
|
148
|
+
const signer = await DfnsSigner.create(defaultConfig);
|
|
149
|
+
mockFetch.mockResolvedValueOnce({
|
|
150
|
+
ok: false,
|
|
151
|
+
status: 500,
|
|
152
|
+
});
|
|
153
|
+
expect(await signer.isAvailable()).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=dfns-signer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dfns-signer.test.js","sourceRoot":"","sources":["../../src/__tests__/dfns-signer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SolanaSigner } from '@solana/keychain-core';
|
|
2
|
+
import { SignerTestConfig, TestScenario } from '@solana/keychain-test-utils';
|
|
3
|
+
export declare const TEST_AUTH_TOKEN = "test-auth-token";
|
|
4
|
+
export declare const TEST_CRED_ID = "test-cred-id";
|
|
5
|
+
export declare const TEST_WALLET_ID = "test-wallet-id";
|
|
6
|
+
export declare const TEST_KEY_ID = "test-key-id";
|
|
7
|
+
export declare const TEST_ED25519_PEM = "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikUmifl1yiWd+IiYyoHBD\n-----END PRIVATE KEY-----";
|
|
8
|
+
export declare const TEST_PUBKEY_HEX = "5da30b28c87836b0ee76ae7b07e3a2e3be1a4c12e48fce3aee18de0a13040b9a";
|
|
9
|
+
export declare function createWalletResponse(overrides?: Partial<{
|
|
10
|
+
status: string;
|
|
11
|
+
scheme: string;
|
|
12
|
+
curve: string;
|
|
13
|
+
}>): {
|
|
14
|
+
id: string;
|
|
15
|
+
network: string;
|
|
16
|
+
signingKey: {
|
|
17
|
+
id: string;
|
|
18
|
+
curve: string;
|
|
19
|
+
publicKey: string;
|
|
20
|
+
scheme: string;
|
|
21
|
+
};
|
|
22
|
+
status: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function createUserActionInitResponse(): {
|
|
25
|
+
allowCredentials: {
|
|
26
|
+
key: {
|
|
27
|
+
id: string;
|
|
28
|
+
}[];
|
|
29
|
+
};
|
|
30
|
+
challenge: string;
|
|
31
|
+
challengeIdentifier: string;
|
|
32
|
+
};
|
|
33
|
+
export declare function createUserActionResponse(): {
|
|
34
|
+
userAction: string;
|
|
35
|
+
};
|
|
36
|
+
export declare function createSignatureResponse(r: string, s: string): {
|
|
37
|
+
id: string;
|
|
38
|
+
signature: {
|
|
39
|
+
r: string;
|
|
40
|
+
s: string;
|
|
41
|
+
};
|
|
42
|
+
status: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function getConfig(scenarios: TestScenario[]): Promise<SignerTestConfig<SolanaSigner>>;
|
|
45
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAG7E,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAC3C,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAGzC,eAAO,MAAM,gBAAgB,6HAEH,CAAC;AAE3B,eAAO,MAAM,eAAe,qEAAqE,CAAC;AAElG,wBAAgB,oBAAoB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;;;;;;;;;;EAY1G;AAED,wBAAgB,4BAA4B;;;;;;;;EAQ3C;AAED,wBAAgB,wBAAwB;;EAIvC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;;;;;;;EAM3D;AAkBD,wBAAsB,SAAS,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAKlG"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createDfnsSigner } from '../dfns-signer.js';
|
|
2
|
+
export const TEST_AUTH_TOKEN = 'test-auth-token';
|
|
3
|
+
export const TEST_CRED_ID = 'test-cred-id';
|
|
4
|
+
export const TEST_WALLET_ID = 'test-wallet-id';
|
|
5
|
+
export const TEST_KEY_ID = 'test-key-id';
|
|
6
|
+
// Ed25519 test key in PKCS#8 PEM format
|
|
7
|
+
export const TEST_ED25519_PEM = `-----BEGIN PRIVATE KEY-----
|
|
8
|
+
MC4CAQAwBQYDK2VwBCIEIJ+DYvh6SEqVTm50DFtMDoQikUmifl1yiWd+IiYyoHBD
|
|
9
|
+
-----END PRIVATE KEY-----`;
|
|
10
|
+
export const TEST_PUBKEY_HEX = '5da30b28c87836b0ee76ae7b07e3a2e3be1a4c12e48fce3aee18de0a13040b9a';
|
|
11
|
+
export function createWalletResponse(overrides) {
|
|
12
|
+
return {
|
|
13
|
+
id: TEST_WALLET_ID,
|
|
14
|
+
network: 'Solana',
|
|
15
|
+
signingKey: {
|
|
16
|
+
id: TEST_KEY_ID,
|
|
17
|
+
curve: overrides?.curve ?? 'ed25519',
|
|
18
|
+
publicKey: TEST_PUBKEY_HEX,
|
|
19
|
+
scheme: overrides?.scheme ?? 'EdDSA',
|
|
20
|
+
},
|
|
21
|
+
status: overrides?.status ?? 'Active',
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function createUserActionInitResponse() {
|
|
25
|
+
return {
|
|
26
|
+
allowCredentials: {
|
|
27
|
+
key: [{ id: TEST_CRED_ID }],
|
|
28
|
+
},
|
|
29
|
+
challenge: 'test-challenge',
|
|
30
|
+
challengeIdentifier: 'test-challenge-id',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function createUserActionResponse() {
|
|
34
|
+
return {
|
|
35
|
+
userAction: 'test-user-action-token',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function createSignatureResponse(r, s) {
|
|
39
|
+
return {
|
|
40
|
+
id: 'sig-123',
|
|
41
|
+
signature: { r, s },
|
|
42
|
+
status: 'Signed',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const SIGNER_TYPE = 'dfns';
|
|
46
|
+
const REQUIRED_ENV_VARS = ['DFNS_AUTH_TOKEN', 'DFNS_CRED_ID', 'DFNS_PRIVATE_KEY_PEM', 'DFNS_WALLET_ID'];
|
|
47
|
+
const CONFIG = {
|
|
48
|
+
signerType: SIGNER_TYPE,
|
|
49
|
+
requiredEnvVars: REQUIRED_ENV_VARS,
|
|
50
|
+
createSigner: () => createDfnsSigner({
|
|
51
|
+
authToken: process.env.DFNS_AUTH_TOKEN,
|
|
52
|
+
credId: process.env.DFNS_CRED_ID,
|
|
53
|
+
privateKeyPem: process.env.DFNS_PRIVATE_KEY_PEM,
|
|
54
|
+
walletId: process.env.DFNS_WALLET_ID,
|
|
55
|
+
apiBaseUrl: process.env.DFNS_API_BASE_URL,
|
|
56
|
+
}),
|
|
57
|
+
};
|
|
58
|
+
export async function getConfig(scenarios) {
|
|
59
|
+
return {
|
|
60
|
+
...CONFIG,
|
|
61
|
+
testScenarios: scenarios,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC;AACjD,MAAM,CAAC,MAAM,YAAY,GAAG,cAAc,CAAC;AAC3C,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAC/C,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AAEzC,wCAAwC;AACxC,MAAM,CAAC,MAAM,gBAAgB,GAAG;;0BAEN,CAAC;AAE3B,MAAM,CAAC,MAAM,eAAe,GAAG,kEAAkE,CAAC;AAElG,MAAM,UAAU,oBAAoB,CAAC,SAAsE;IACvG,OAAO;QACH,EAAE,EAAE,cAAc;QAClB,OAAO,EAAE,QAAQ;QACjB,UAAU,EAAE;YACR,EAAE,EAAE,WAAW;YACf,KAAK,EAAE,SAAS,EAAE,KAAK,IAAI,SAAS;YACpC,SAAS,EAAE,eAAe;YAC1B,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,OAAO;SACvC;QACD,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,QAAQ;KACxC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,4BAA4B;IACxC,OAAO;QACH,gBAAgB,EAAE;YACd,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC;SAC9B;QACD,SAAS,EAAE,gBAAgB;QAC3B,mBAAmB,EAAE,mBAAmB;KAC3C,CAAC;AACN,CAAC;AAED,MAAM,UAAU,wBAAwB;IACpC,OAAO;QACH,UAAU,EAAE,wBAAwB;KACvC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,CAAS,EAAE,CAAS;IACxD,OAAO;QACH,EAAE,EAAE,SAAS;QACb,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE;QACnB,MAAM,EAAE,QAAQ;KACnB,CAAC;AACN,CAAC;AAED,MAAM,WAAW,GAAG,MAAM,CAAC;AAC3B,MAAM,iBAAiB,GAAG,CAAC,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,gBAAgB,CAAC,CAAC;AAExG,MAAM,MAAM,GAAmC;IAC3C,UAAU,EAAE,WAAW;IACvB,eAAe,EAAE,iBAAiB;IAClC,YAAY,EAAE,GAAG,EAAE,CACf,gBAAgB,CAAC;QACb,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,eAAgB;QACvC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,YAAa;QACjC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAqB;QAChD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,cAAe;QACrC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;KAC5C,CAAC;CACT,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,SAAyB;IACrD,OAAO;QACH,GAAG,MAAM;QACT,aAAa,EAAE,SAAS;KAC3B,CAAC;AACN,CAAC"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perform the Dfns User Action Signing flow. For more details, see https://docs.dfns.co/api-reference/auth/signing-flows#asymetric-keys-signing-flow
|
|
3
|
+
*
|
|
4
|
+
* @returns The `userAction` token to include as `x-dfns-useraction` header.
|
|
5
|
+
*/
|
|
6
|
+
export declare function signUserAction(apiBaseUrl: string, authToken: string, credId: string, privateKeyPem: string, httpMethod: string, httpPath: string, body: string): Promise<string>;
|
|
7
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAsB,cAAc,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAoHjB"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import { base64UrlDecoder, SignerErrorCode, throwSignerError } from '@solana/keychain-core';
|
|
3
|
+
/**
|
|
4
|
+
* Perform the Dfns User Action Signing flow. For more details, see https://docs.dfns.co/api-reference/auth/signing-flows#asymetric-keys-signing-flow
|
|
5
|
+
*
|
|
6
|
+
* @returns The `userAction` token to include as `x-dfns-useraction` header.
|
|
7
|
+
*/
|
|
8
|
+
export async function signUserAction(apiBaseUrl, authToken, credId, privateKeyPem, httpMethod, httpPath, body) {
|
|
9
|
+
// Request a challenge
|
|
10
|
+
const initUrl = `${apiBaseUrl}/auth/action/init`;
|
|
11
|
+
let initResponse;
|
|
12
|
+
try {
|
|
13
|
+
initResponse = await fetch(initUrl, {
|
|
14
|
+
body: JSON.stringify({
|
|
15
|
+
userActionHttpMethod: httpMethod,
|
|
16
|
+
userActionHttpPath: httpPath,
|
|
17
|
+
userActionPayload: body,
|
|
18
|
+
userActionServerKind: 'Api',
|
|
19
|
+
}),
|
|
20
|
+
headers: {
|
|
21
|
+
Authorization: `Bearer ${authToken}`,
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
},
|
|
24
|
+
method: 'POST',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
throwSignerError(SignerErrorCode.HTTP_ERROR, {
|
|
29
|
+
cause: error,
|
|
30
|
+
message: 'Dfns network request failed',
|
|
31
|
+
url: initUrl,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (!initResponse.ok) {
|
|
35
|
+
const errorText = await initResponse.text().catch(() => 'Failed to read error response');
|
|
36
|
+
throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
|
|
37
|
+
message: `Dfns auth/action/init failed: ${initResponse.status}`,
|
|
38
|
+
response: errorText,
|
|
39
|
+
status: initResponse.status,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
let challenge;
|
|
43
|
+
try {
|
|
44
|
+
challenge = (await initResponse.json());
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
48
|
+
cause: error,
|
|
49
|
+
message: 'Failed to parse Dfns auth challenge response',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// Verify credential is allowed
|
|
53
|
+
const allowed = challenge.allowCredentials.key.some(c => c.id === credId);
|
|
54
|
+
if (!allowed) {
|
|
55
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
56
|
+
message: `Credential ${credId} not in allowed credentials`,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Sign the challenge
|
|
60
|
+
const clientData = new TextEncoder().encode(JSON.stringify({
|
|
61
|
+
challenge: challenge.challenge,
|
|
62
|
+
type: 'key.get',
|
|
63
|
+
}));
|
|
64
|
+
const signature = crypto.sign(undefined, clientData, privateKeyPem);
|
|
65
|
+
const clientDataB64 = base64UrlDecoder(clientData);
|
|
66
|
+
const signatureB64 = base64UrlDecoder(new Uint8Array(signature));
|
|
67
|
+
// Submit the signed challenge
|
|
68
|
+
const actionUrl = `${apiBaseUrl}/auth/action`;
|
|
69
|
+
let signResponse;
|
|
70
|
+
try {
|
|
71
|
+
signResponse = await fetch(actionUrl, {
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
challengeIdentifier: challenge.challengeIdentifier,
|
|
74
|
+
firstFactor: {
|
|
75
|
+
credentialAssertion: {
|
|
76
|
+
clientData: clientDataB64,
|
|
77
|
+
credId,
|
|
78
|
+
signature: signatureB64,
|
|
79
|
+
},
|
|
80
|
+
kind: 'Key',
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
headers: {
|
|
84
|
+
Authorization: `Bearer ${authToken}`,
|
|
85
|
+
'Content-Type': 'application/json',
|
|
86
|
+
},
|
|
87
|
+
method: 'POST',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
throwSignerError(SignerErrorCode.HTTP_ERROR, {
|
|
92
|
+
cause: error,
|
|
93
|
+
message: 'Dfns network request failed',
|
|
94
|
+
url: actionUrl,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (!signResponse.ok) {
|
|
98
|
+
const errorText = await signResponse.text().catch(() => 'Failed to read error response');
|
|
99
|
+
throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
|
|
100
|
+
message: `Dfns auth/action failed: ${signResponse.status}`,
|
|
101
|
+
response: errorText,
|
|
102
|
+
status: signResponse.status,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
let actionResponse;
|
|
106
|
+
try {
|
|
107
|
+
actionResponse = (await signResponse.json());
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
111
|
+
cause: error,
|
|
112
|
+
message: 'Failed to parse Dfns auth action response',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return actionResponse.userAction;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|