@solana/keychain-core 0.0.0 → 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/README.md +124 -0
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +44 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +61 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +85 -0
- package/dist/utils.js.map +1 -0
- package/package.json +44 -9
- package/src/errors.ts +49 -0
- package/src/index.ts +3 -0
- package/src/types.ts +47 -0
- package/src/utils.ts +115 -0
- package/index.js +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# @solana/keychain-core
|
|
2
|
+
|
|
3
|
+
Core interfaces and utilities for building external Solana signers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @solana/keychain-core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What's Included
|
|
12
|
+
|
|
13
|
+
### Interfaces
|
|
14
|
+
|
|
15
|
+
**`SolanaSigner`** - Unified interface that all signer implementations extend:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { SolanaSigner } from '@solana/keychain-core';
|
|
19
|
+
|
|
20
|
+
interface SolanaSigner {
|
|
21
|
+
address: Address;
|
|
22
|
+
isAvailable(): Promise<boolean>;
|
|
23
|
+
signMessages(messages: readonly SignableMessage[]): Promise<readonly SignatureDictionary[]>;
|
|
24
|
+
signTransactions(transactions: readonly Transaction[]): Promise<readonly SignatureDictionary[]>;
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Error Handling
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { SignerError, SignerErrorCode, throwSignerError } from '@solana/keychain-core';
|
|
32
|
+
|
|
33
|
+
// Check error type
|
|
34
|
+
if (error instanceof SignerError) {
|
|
35
|
+
console.log(error.code); // e.g., 'SIGNER_SIGNING_FAILED'
|
|
36
|
+
console.log(error.context); // Additional error details
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Throw typed errors
|
|
40
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
41
|
+
address: 'signer-address',
|
|
42
|
+
message: 'Custom error message'
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Available error codes:**
|
|
47
|
+
- `INVALID_PRIVATE_KEY` - Invalid private key format
|
|
48
|
+
- `INVALID_PUBLIC_KEY` - Invalid public key format
|
|
49
|
+
- `SIGNING_FAILED` - Signing operation failed
|
|
50
|
+
- `REMOTE_API_ERROR` - Remote signer API error
|
|
51
|
+
- `HTTP_ERROR` - HTTP request failed
|
|
52
|
+
- `SERIALIZATION_ERROR` - Transaction serialization failed
|
|
53
|
+
- `CONFIG_ERROR` - Invalid configuration
|
|
54
|
+
- `NOT_AVAILABLE` - Signer not available/healthy
|
|
55
|
+
- `IO_ERROR` - File I/O error
|
|
56
|
+
- `PRIVY_NOT_INITIALIZED` - Privy signer not initialized
|
|
57
|
+
|
|
58
|
+
### Utilities
|
|
59
|
+
|
|
60
|
+
**`extractSignatureFromWireTransaction`** - Extract a specific signer's signature from a signed transaction:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { extractSignatureFromWireTransaction } from '@solana/keychain-core';
|
|
64
|
+
|
|
65
|
+
// When a remote API returns a fully signed base64 transaction, we need to extract the signature to use Kit's native methods (which rely on .signTransactions to return a SignatureDictionary)
|
|
66
|
+
const signedTx = await remoteApi.signTransaction(...);
|
|
67
|
+
const sigDict = extractSignatureFromWireTransaction({
|
|
68
|
+
base64WireTransaction: signedTx,
|
|
69
|
+
signerAddress: myAddress
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**`createSignatureDictionary`** - Create a signature dictionary from raw signature bytes:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { createSignatureDictionary } from '@solana/keychain-core';
|
|
77
|
+
|
|
78
|
+
const sigDict = createSignatureDictionary({
|
|
79
|
+
signature: signatureBytes,
|
|
80
|
+
signerAddress: myAddress
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Usage
|
|
85
|
+
|
|
86
|
+
This package is typically used as a dependency when building custom signer implementations. See [@solana/keychain-privy](https://www.npmjs.com/package/@solana/keychain-privy) for an example implementation.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { SolanaSigner, SignerErrorCode, throwSignerError } from '@solana/keychain-core';
|
|
90
|
+
|
|
91
|
+
class MyCustomSigner implements SolanaSigner {
|
|
92
|
+
readonly address: Address;
|
|
93
|
+
|
|
94
|
+
async isAvailable(): Promise<boolean> {
|
|
95
|
+
// Check if backend is healthy
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async signMessages(messages: readonly SignableMessage[]) {
|
|
99
|
+
// Sign messages using your backend
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async signTransactions(transactions: readonly Transaction[]) {
|
|
103
|
+
// Sign transactions using your backend
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Type Guards
|
|
109
|
+
|
|
110
|
+
**`isSolanaSigner`** - Check if a value is a SolanaSigner:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { isSolanaSigner } from '@solana/keychain-core';
|
|
114
|
+
|
|
115
|
+
const isSigner = isSolanaSigner(value); // true or false
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**`assertIsSolanaSigner`** - Assert that a value is a SolanaSigner:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { assertIsSolanaSigner } from '@solana/keychain-core';
|
|
122
|
+
|
|
123
|
+
assertIsSolanaSigner(value); // void (throws if not a SolanaSigner)
|
|
124
|
+
```
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error codes for solana-keychain, specific to this library
|
|
3
|
+
*/
|
|
4
|
+
export declare enum SignerErrorCode {
|
|
5
|
+
INVALID_PRIVATE_KEY = "SIGNER_INVALID_PRIVATE_KEY",
|
|
6
|
+
INVALID_PUBLIC_KEY = "SIGNER_INVALID_PUBLIC_KEY",
|
|
7
|
+
SIGNING_FAILED = "SIGNER_SIGNING_FAILED",
|
|
8
|
+
REMOTE_API_ERROR = "SIGNER_REMOTE_API_ERROR",
|
|
9
|
+
HTTP_ERROR = "SIGNER_HTTP_ERROR",
|
|
10
|
+
SERIALIZATION_ERROR = "SIGNER_SERIALIZATION_ERROR",
|
|
11
|
+
PARSING_ERROR = "SIGNER_PARSING_ERROR",
|
|
12
|
+
CONFIG_ERROR = "SIGNER_CONFIG_ERROR",
|
|
13
|
+
NOT_AVAILABLE = "SIGNER_NOT_AVAILABLE",
|
|
14
|
+
IO_ERROR = "SIGNER_IO_ERROR",
|
|
15
|
+
SIGNER_NOT_INITIALIZED = "SIGNER_NOT_INITIALIZED",
|
|
16
|
+
EXPECTED_SOLANA_SIGNER = "SIGNER_EXPECTED_SOLANA_SIGNER"
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Custom error class for signer-specific errors
|
|
20
|
+
* Extends Error with code and context properties
|
|
21
|
+
*/
|
|
22
|
+
export declare class SignerError extends Error {
|
|
23
|
+
readonly code: SignerErrorCode;
|
|
24
|
+
readonly context?: Record<string, unknown>;
|
|
25
|
+
constructor(code: SignerErrorCode, context?: Record<string, unknown>);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Helper function to create signer-specific errors
|
|
29
|
+
*/
|
|
30
|
+
export declare function createSignerError(code: SignerErrorCode, context?: Record<string, unknown>): SignerError;
|
|
31
|
+
/**
|
|
32
|
+
* Helper function to throw signer-specific errors
|
|
33
|
+
*/
|
|
34
|
+
export declare function throwSignerError(code: SignerErrorCode, context?: Record<string, unknown>): never;
|
|
35
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,eAAe;IACvB,mBAAmB,+BAA+B;IAClD,kBAAkB,8BAA8B;IAChD,cAAc,0BAA0B;IACxC,gBAAgB,4BAA4B;IAC5C,UAAU,sBAAsB;IAChC,mBAAmB,+BAA+B;IAClD,aAAa,yBAAyB;IACtC,YAAY,wBAAwB;IACpC,aAAa,yBAAyB;IACtC,QAAQ,oBAAoB;IAC5B,sBAAsB,2BAA2B;IACjD,sBAAsB,kCAAkC;CAC3D;AAED;;;GAGG;AACH,qBAAa,WAAY,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAE/B,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQvE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAEvG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAEhG"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error codes for solana-keychain, specific to this library
|
|
3
|
+
*/
|
|
4
|
+
export var SignerErrorCode;
|
|
5
|
+
(function (SignerErrorCode) {
|
|
6
|
+
SignerErrorCode["INVALID_PRIVATE_KEY"] = "SIGNER_INVALID_PRIVATE_KEY";
|
|
7
|
+
SignerErrorCode["INVALID_PUBLIC_KEY"] = "SIGNER_INVALID_PUBLIC_KEY";
|
|
8
|
+
SignerErrorCode["SIGNING_FAILED"] = "SIGNER_SIGNING_FAILED";
|
|
9
|
+
SignerErrorCode["REMOTE_API_ERROR"] = "SIGNER_REMOTE_API_ERROR";
|
|
10
|
+
SignerErrorCode["HTTP_ERROR"] = "SIGNER_HTTP_ERROR";
|
|
11
|
+
SignerErrorCode["SERIALIZATION_ERROR"] = "SIGNER_SERIALIZATION_ERROR";
|
|
12
|
+
SignerErrorCode["PARSING_ERROR"] = "SIGNER_PARSING_ERROR";
|
|
13
|
+
SignerErrorCode["CONFIG_ERROR"] = "SIGNER_CONFIG_ERROR";
|
|
14
|
+
SignerErrorCode["NOT_AVAILABLE"] = "SIGNER_NOT_AVAILABLE";
|
|
15
|
+
SignerErrorCode["IO_ERROR"] = "SIGNER_IO_ERROR";
|
|
16
|
+
SignerErrorCode["SIGNER_NOT_INITIALIZED"] = "SIGNER_NOT_INITIALIZED";
|
|
17
|
+
SignerErrorCode["EXPECTED_SOLANA_SIGNER"] = "SIGNER_EXPECTED_SOLANA_SIGNER";
|
|
18
|
+
})(SignerErrorCode || (SignerErrorCode = {}));
|
|
19
|
+
/**
|
|
20
|
+
* Custom error class for signer-specific errors
|
|
21
|
+
* Extends Error with code and context properties
|
|
22
|
+
*/
|
|
23
|
+
export class SignerError extends Error {
|
|
24
|
+
constructor(code, context) {
|
|
25
|
+
const message = context?.message && typeof context.message === 'string' ? context.message : `Signer error: ${code}`;
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'SignerError';
|
|
28
|
+
this.code = code;
|
|
29
|
+
this.context = context;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Helper function to create signer-specific errors
|
|
34
|
+
*/
|
|
35
|
+
export function createSignerError(code, context) {
|
|
36
|
+
return new SignerError(code, context);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Helper function to throw signer-specific errors
|
|
40
|
+
*/
|
|
41
|
+
export function throwSignerError(code, context) {
|
|
42
|
+
throw createSignerError(code, context);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAY,eAaX;AAbD,WAAY,eAAe;IACvB,qEAAkD,CAAA;IAClD,mEAAgD,CAAA;IAChD,2DAAwC,CAAA;IACxC,+DAA4C,CAAA;IAC5C,mDAAgC,CAAA;IAChC,qEAAkD,CAAA;IAClD,yDAAsC,CAAA;IACtC,uDAAoC,CAAA;IACpC,yDAAsC,CAAA;IACtC,+CAA4B,CAAA;IAC5B,oEAAiD,CAAA;IACjD,2EAAwD,CAAA;AAC5D,CAAC,EAbW,eAAe,KAAf,eAAe,QAa1B;AAED;;;GAGG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAIlC,YAAY,IAAqB,EAAE,OAAiC;QAChE,MAAM,OAAO,GACT,OAAO,EAAE,OAAO,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,IAAI,EAAE,CAAC;QACxG,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAqB,EAAE,OAAiC;IACtF,OAAO,IAAI,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAqB,EAAE,OAAiC;IACrF,MAAM,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Address } from '@solana/addresses';
|
|
2
|
+
import type { MessagePartialSigner, SignableMessage, SignatureDictionary, TransactionPartialSigner } from '@solana/signers';
|
|
3
|
+
import type { Transaction, TransactionWithinSizeLimit, TransactionWithLifetime } from '@solana/transactions';
|
|
4
|
+
/**
|
|
5
|
+
* Unified signer interface that extends both transaction and message signers.
|
|
6
|
+
* Provides both high-level (simple) and low-level (@solana/kit compatible) APIs.
|
|
7
|
+
*/
|
|
8
|
+
export interface SolanaSigner<TAddress extends string = string> extends TransactionPartialSigner<TAddress>, MessagePartialSigner<TAddress> {
|
|
9
|
+
/**
|
|
10
|
+
* Get the public key address of this signer
|
|
11
|
+
*/
|
|
12
|
+
readonly address: Address<TAddress>;
|
|
13
|
+
/**
|
|
14
|
+
* Check if the signer is available and healthy.
|
|
15
|
+
* For remote signers (Vault, Privy, Turnkey), this performs an API health check.
|
|
16
|
+
*/
|
|
17
|
+
isAvailable(): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Signs multiple messages and returns signature dictionaries
|
|
20
|
+
* for @solana/kit signing compatibility.
|
|
21
|
+
*
|
|
22
|
+
* @param messages - Array of signable messages
|
|
23
|
+
* @returns Array of signature dictionaries (address -> signature mapping)
|
|
24
|
+
*/
|
|
25
|
+
signMessages(messages: readonly SignableMessage[]): Promise<readonly SignatureDictionary[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Signs multiple transactions and returns signature dictionaries.
|
|
28
|
+
* for @solana/kit signing compatibility.
|
|
29
|
+
*
|
|
30
|
+
* @param transactions - Array of transactions to sign
|
|
31
|
+
* @returns Array of signature dictionaries (address -> signature mapping)
|
|
32
|
+
*/
|
|
33
|
+
signTransactions(transactions: readonly (Transaction & TransactionWithinSizeLimit & TransactionWithLifetime)[]): Promise<readonly SignatureDictionary[]>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EACR,oBAAoB,EACpB,eAAe,EACf,mBAAmB,EACnB,wBAAwB,EAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,WAAW,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE7G;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,CAC1D,SAAQ,wBAAwB,CAAC,QAAQ,CAAC,EACtC,oBAAoB,CAAC,QAAQ,CAAC;IAClC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEpC;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC;;;;;;OAMG;IACH,YAAY,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC,CAAC;IAE5F;;;;;;OAMG;IACH,gBAAgB,CACZ,YAAY,EAAE,SAAS,CAAC,WAAW,GAAG,0BAA0B,GAAG,uBAAuB,CAAC,EAAE,GAC9F,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC,CAAC;CAC9C"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Address } from '@solana/addresses';
|
|
2
|
+
import { SignatureBytes } from '@solana/keys';
|
|
3
|
+
import { SignatureDictionary } from '@solana/signers';
|
|
4
|
+
import { Base64EncodedWireTransaction } from '@solana/transactions';
|
|
5
|
+
import { SolanaSigner } from './types.js';
|
|
6
|
+
interface ExtractSignatureFromWireTransactionOptions {
|
|
7
|
+
base64WireTransaction: Base64EncodedWireTransaction;
|
|
8
|
+
signerAddress: Address;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Extracts a specific signer's signature from a base64-encoded wire transaction.
|
|
12
|
+
* Useful for remote signers that return fully signed transactions from their APIs.
|
|
13
|
+
*
|
|
14
|
+
* @param base64WireTransaction - Base64 encoded transaction string
|
|
15
|
+
* @param signerAddress - The address of the signer whose signature to extract
|
|
16
|
+
* @returns SignatureDictionary with only the specified signer's signature
|
|
17
|
+
* @throws {SignerError} If no signature is found for the given address
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // Privy API returns a signed transaction
|
|
22
|
+
* const signedTx = await privyApi.signTransaction(...);
|
|
23
|
+
* const sigDict = extractSignatureFromWireTransaction(signedTx, this.address);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractSignatureFromWireTransaction({ base64WireTransaction, signerAddress, }: ExtractSignatureFromWireTransactionOptions): SignatureDictionary;
|
|
27
|
+
interface CreateSignatureDictionaryArgs {
|
|
28
|
+
signature: SignatureBytes;
|
|
29
|
+
signerAddress: Address;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a signature dictionary from a signature and signer address.
|
|
33
|
+
* @param signature - The signature to create the dictionary from
|
|
34
|
+
* @param signerAddress - The address of the signer whose signature to create the dictionary from
|
|
35
|
+
* @returns SignatureDictionary with only the specified signer's signature
|
|
36
|
+
* @throws {SignerError} If no signature is found for the given address
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const sigDict = createSignatureDictionary({ signature, signerAddress });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare function createSignatureDictionary({ signature, signerAddress, }: CreateSignatureDictionaryArgs): SignatureDictionary;
|
|
44
|
+
/**
|
|
45
|
+
* Checks if the given value is a SolanaSigner.
|
|
46
|
+
* @param value - The value to check
|
|
47
|
+
* @returns True if the value is a SolanaSigner, false otherwise
|
|
48
|
+
*/
|
|
49
|
+
export declare function isSolanaSigner<TAddress extends string>(value: {
|
|
50
|
+
address: Address<TAddress>;
|
|
51
|
+
}): value is SolanaSigner<TAddress>;
|
|
52
|
+
/**
|
|
53
|
+
* Asserts that the given value is a SolanaSigner, throwing an error if it is not.
|
|
54
|
+
* @param value - The value to check
|
|
55
|
+
* @throws {SignerError} If the value is not a SolanaSigner
|
|
56
|
+
*/
|
|
57
|
+
export declare function assertIsSolanaSigner<TAddress extends string>(value: {
|
|
58
|
+
address: Address<TAddress>;
|
|
59
|
+
}): asserts value is SolanaSigner<TAddress>;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAsD,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC1G,OAAO,EAAE,4BAA4B,EAAyB,MAAM,sBAAsB,CAAC;AAG3F,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,UAAU,0CAA0C;IAChD,qBAAqB,EAAE,4BAA4B,CAAC;IACpD,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mCAAmC,CAAC,EAChD,qBAAqB,EACrB,aAAa,GAChB,EAAE,0CAA0C,GAAG,mBAAmB,CAmBlE;AAED,UAAU,6BAA6B;IACnC,SAAS,EAAE,cAAc,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,EACtC,SAAS,EACT,aAAa,GAChB,EAAE,6BAA6B,GAAG,mBAAmB,CASrD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAS,MAAM,EAAE,KAAK,EAAE;IAC3D,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC9B,GAAG,KAAK,IAAI,YAAY,CAAC,QAAQ,CAAC,CAOlC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,SAAS,MAAM,EAAE,KAAK,EAAE;IACjE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC9B,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC,QAAQ,CAAC,CAM1C"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { assertIsAddress } from '@solana/addresses';
|
|
2
|
+
import { getBase64Encoder } from '@solana/codecs-strings';
|
|
3
|
+
import { isMessagePartialSigner, isTransactionPartialSigner } from '@solana/signers';
|
|
4
|
+
import { getTransactionDecoder } from '@solana/transactions';
|
|
5
|
+
import { SignerErrorCode, throwSignerError } from './errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* Extracts a specific signer's signature from a base64-encoded wire transaction.
|
|
8
|
+
* Useful for remote signers that return fully signed transactions from their APIs.
|
|
9
|
+
*
|
|
10
|
+
* @param base64WireTransaction - Base64 encoded transaction string
|
|
11
|
+
* @param signerAddress - The address of the signer whose signature to extract
|
|
12
|
+
* @returns SignatureDictionary with only the specified signer's signature
|
|
13
|
+
* @throws {SignerError} If no signature is found for the given address
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Privy API returns a signed transaction
|
|
18
|
+
* const signedTx = await privyApi.signTransaction(...);
|
|
19
|
+
* const sigDict = extractSignatureFromWireTransaction(signedTx, this.address);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function extractSignatureFromWireTransaction({ base64WireTransaction, signerAddress, }) {
|
|
23
|
+
assertIsAddress(signerAddress);
|
|
24
|
+
const encoder = getBase64Encoder();
|
|
25
|
+
const decoder = getTransactionDecoder();
|
|
26
|
+
const transactionBytes = encoder.encode(base64WireTransaction);
|
|
27
|
+
const { signatures } = decoder.decode(transactionBytes);
|
|
28
|
+
const signature = signatures[signerAddress];
|
|
29
|
+
if (!signature) {
|
|
30
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
31
|
+
address: signerAddress,
|
|
32
|
+
message: `No signature found for address ${signerAddress}`,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return createSignatureDictionary({
|
|
36
|
+
signature,
|
|
37
|
+
signerAddress,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a signature dictionary from a signature and signer address.
|
|
42
|
+
* @param signature - The signature to create the dictionary from
|
|
43
|
+
* @param signerAddress - The address of the signer whose signature to create the dictionary from
|
|
44
|
+
* @returns SignatureDictionary with only the specified signer's signature
|
|
45
|
+
* @throws {SignerError} If no signature is found for the given address
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const sigDict = createSignatureDictionary({ signature, signerAddress });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function createSignatureDictionary({ signature, signerAddress, }) {
|
|
53
|
+
assertIsAddress(signerAddress);
|
|
54
|
+
if (!signature) {
|
|
55
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
56
|
+
address: signerAddress,
|
|
57
|
+
message: `No signature found for address ${signerAddress}`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return Object.freeze({ [signerAddress]: signature });
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Checks if the given value is a SolanaSigner.
|
|
64
|
+
* @param value - The value to check
|
|
65
|
+
* @returns True if the value is a SolanaSigner, false otherwise
|
|
66
|
+
*/
|
|
67
|
+
export function isSolanaSigner(value) {
|
|
68
|
+
return ('address' in value &&
|
|
69
|
+
'isAvailable' in value &&
|
|
70
|
+
isMessagePartialSigner(value) &&
|
|
71
|
+
isTransactionPartialSigner(value));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Asserts that the given value is a SolanaSigner, throwing an error if it is not.
|
|
75
|
+
* @param value - The value to check
|
|
76
|
+
* @throws {SignerError} If the value is not a SolanaSigner
|
|
77
|
+
*/
|
|
78
|
+
export function assertIsSolanaSigner(value) {
|
|
79
|
+
if (!isSolanaSigner(value)) {
|
|
80
|
+
throwSignerError(SignerErrorCode.EXPECTED_SOLANA_SIGNER, {
|
|
81
|
+
address: value.address,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAuB,MAAM,iBAAiB,CAAC;AAC1G,OAAO,EAAgC,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE3F,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQhE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,mCAAmC,CAAC,EAChD,qBAAqB,EACrB,aAAa,GAC4B;IACzC,eAAe,CAAC,aAAa,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAC/D,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAExD,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,gBAAgB,CAAC,eAAe,CAAC,cAAc,EAAE;YAC7C,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,kCAAkC,aAAa,EAAE;SAC7D,CAAC,CAAC;IACP,CAAC;IAED,OAAO,yBAAyB,CAAC;QAC7B,SAAS;QACT,aAAa;KAChB,CAAC,CAAC;AACP,CAAC;AAOD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAC,EACtC,SAAS,EACT,aAAa,GACe;IAC5B,eAAe,CAAC,aAAa,CAAC,CAAC;IAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,gBAAgB,CAAC,eAAe,CAAC,cAAc,EAAE;YAC7C,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,kCAAkC,aAAa,EAAE;SAC7D,CAAC,CAAC;IACP,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAA0B,KAEvD;IACG,OAAO,CACH,SAAS,IAAI,KAAK;QAClB,aAAa,IAAI,KAAK;QACtB,sBAAsB,CAAC,KAAK,CAAC;QAC7B,0BAA0B,CAAC,KAAK,CAAC,CACpC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAA0B,KAE7D;IACG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,gBAAgB,CAAC,eAAe,CAAC,sBAAsB,EAAE;YACrD,OAAO,EAAE,KAAK,CAAC,OAAO;SACzB,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/keychain-core",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"author": "Solana Foundation",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": "https://github.com/solana-foundation/solana-keychain",
|
|
6
|
+
"version": "0.3.0",
|
|
7
|
+
"description": "Core interfaces and types for external Solana signers",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"solana",
|
|
10
|
+
"signing",
|
|
11
|
+
"wallet",
|
|
12
|
+
"privy",
|
|
13
|
+
"vault",
|
|
14
|
+
"turnkey"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"src"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@solana/addresses": "^5.0.0",
|
|
32
|
+
"@solana/codecs-core": "^5.0.0",
|
|
33
|
+
"@solana/codecs-strings": "^5.0.0",
|
|
34
|
+
"@solana/keys": "^5.0.0",
|
|
35
|
+
"@solana/signers": "^5.0.0",
|
|
36
|
+
"@solana/transactions": "^5.0.0"
|
|
7
37
|
},
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc --build",
|
|
43
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
44
|
+
"test": "pnpm run typecheck",
|
|
45
|
+
"typecheck": "tsc --noEmit"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error codes for solana-keychain, specific to this library
|
|
3
|
+
*/
|
|
4
|
+
export enum SignerErrorCode {
|
|
5
|
+
INVALID_PRIVATE_KEY = 'SIGNER_INVALID_PRIVATE_KEY',
|
|
6
|
+
INVALID_PUBLIC_KEY = 'SIGNER_INVALID_PUBLIC_KEY',
|
|
7
|
+
SIGNING_FAILED = 'SIGNER_SIGNING_FAILED',
|
|
8
|
+
REMOTE_API_ERROR = 'SIGNER_REMOTE_API_ERROR',
|
|
9
|
+
HTTP_ERROR = 'SIGNER_HTTP_ERROR',
|
|
10
|
+
SERIALIZATION_ERROR = 'SIGNER_SERIALIZATION_ERROR',
|
|
11
|
+
PARSING_ERROR = 'SIGNER_PARSING_ERROR',
|
|
12
|
+
CONFIG_ERROR = 'SIGNER_CONFIG_ERROR',
|
|
13
|
+
NOT_AVAILABLE = 'SIGNER_NOT_AVAILABLE',
|
|
14
|
+
IO_ERROR = 'SIGNER_IO_ERROR',
|
|
15
|
+
SIGNER_NOT_INITIALIZED = 'SIGNER_NOT_INITIALIZED',
|
|
16
|
+
EXPECTED_SOLANA_SIGNER = 'SIGNER_EXPECTED_SOLANA_SIGNER',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Custom error class for signer-specific errors
|
|
21
|
+
* Extends Error with code and context properties
|
|
22
|
+
*/
|
|
23
|
+
export class SignerError extends Error {
|
|
24
|
+
readonly code: SignerErrorCode;
|
|
25
|
+
readonly context?: Record<string, unknown>;
|
|
26
|
+
|
|
27
|
+
constructor(code: SignerErrorCode, context?: Record<string, unknown>) {
|
|
28
|
+
const message =
|
|
29
|
+
context?.message && typeof context.message === 'string' ? context.message : `Signer error: ${code}`;
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = 'SignerError';
|
|
32
|
+
this.code = code;
|
|
33
|
+
this.context = context;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Helper function to create signer-specific errors
|
|
39
|
+
*/
|
|
40
|
+
export function createSignerError(code: SignerErrorCode, context?: Record<string, unknown>): SignerError {
|
|
41
|
+
return new SignerError(code, context);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Helper function to throw signer-specific errors
|
|
46
|
+
*/
|
|
47
|
+
export function throwSignerError(code: SignerErrorCode, context?: Record<string, unknown>): never {
|
|
48
|
+
throw createSignerError(code, context);
|
|
49
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Address } from '@solana/addresses';
|
|
2
|
+
import type {
|
|
3
|
+
MessagePartialSigner,
|
|
4
|
+
SignableMessage,
|
|
5
|
+
SignatureDictionary,
|
|
6
|
+
TransactionPartialSigner,
|
|
7
|
+
} from '@solana/signers';
|
|
8
|
+
import type { Transaction, TransactionWithinSizeLimit, TransactionWithLifetime } from '@solana/transactions';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unified signer interface that extends both transaction and message signers.
|
|
12
|
+
* Provides both high-level (simple) and low-level (@solana/kit compatible) APIs.
|
|
13
|
+
*/
|
|
14
|
+
export interface SolanaSigner<TAddress extends string = string>
|
|
15
|
+
extends TransactionPartialSigner<TAddress>,
|
|
16
|
+
MessagePartialSigner<TAddress> {
|
|
17
|
+
/**
|
|
18
|
+
* Get the public key address of this signer
|
|
19
|
+
*/
|
|
20
|
+
readonly address: Address<TAddress>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check if the signer is available and healthy.
|
|
24
|
+
* For remote signers (Vault, Privy, Turnkey), this performs an API health check.
|
|
25
|
+
*/
|
|
26
|
+
isAvailable(): Promise<boolean>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Signs multiple messages and returns signature dictionaries
|
|
30
|
+
* for @solana/kit signing compatibility.
|
|
31
|
+
*
|
|
32
|
+
* @param messages - Array of signable messages
|
|
33
|
+
* @returns Array of signature dictionaries (address -> signature mapping)
|
|
34
|
+
*/
|
|
35
|
+
signMessages(messages: readonly SignableMessage[]): Promise<readonly SignatureDictionary[]>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Signs multiple transactions and returns signature dictionaries.
|
|
39
|
+
* for @solana/kit signing compatibility.
|
|
40
|
+
*
|
|
41
|
+
* @param transactions - Array of transactions to sign
|
|
42
|
+
* @returns Array of signature dictionaries (address -> signature mapping)
|
|
43
|
+
*/
|
|
44
|
+
signTransactions(
|
|
45
|
+
transactions: readonly (Transaction & TransactionWithinSizeLimit & TransactionWithLifetime)[],
|
|
46
|
+
): Promise<readonly SignatureDictionary[]>;
|
|
47
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Address, assertIsAddress } from '@solana/addresses';
|
|
2
|
+
import { getBase64Encoder } from '@solana/codecs-strings';
|
|
3
|
+
import { SignatureBytes } from '@solana/keys';
|
|
4
|
+
import { isMessagePartialSigner, isTransactionPartialSigner, SignatureDictionary } from '@solana/signers';
|
|
5
|
+
import { Base64EncodedWireTransaction, getTransactionDecoder } from '@solana/transactions';
|
|
6
|
+
|
|
7
|
+
import { SignerErrorCode, throwSignerError } from './errors.js';
|
|
8
|
+
import { SolanaSigner } from './types.js';
|
|
9
|
+
|
|
10
|
+
interface ExtractSignatureFromWireTransactionOptions {
|
|
11
|
+
base64WireTransaction: Base64EncodedWireTransaction;
|
|
12
|
+
signerAddress: Address;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extracts a specific signer's signature from a base64-encoded wire transaction.
|
|
17
|
+
* Useful for remote signers that return fully signed transactions from their APIs.
|
|
18
|
+
*
|
|
19
|
+
* @param base64WireTransaction - Base64 encoded transaction string
|
|
20
|
+
* @param signerAddress - The address of the signer whose signature to extract
|
|
21
|
+
* @returns SignatureDictionary with only the specified signer's signature
|
|
22
|
+
* @throws {SignerError} If no signature is found for the given address
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Privy API returns a signed transaction
|
|
27
|
+
* const signedTx = await privyApi.signTransaction(...);
|
|
28
|
+
* const sigDict = extractSignatureFromWireTransaction(signedTx, this.address);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function extractSignatureFromWireTransaction({
|
|
32
|
+
base64WireTransaction,
|
|
33
|
+
signerAddress,
|
|
34
|
+
}: ExtractSignatureFromWireTransactionOptions): SignatureDictionary {
|
|
35
|
+
assertIsAddress(signerAddress);
|
|
36
|
+
const encoder = getBase64Encoder();
|
|
37
|
+
const decoder = getTransactionDecoder();
|
|
38
|
+
const transactionBytes = encoder.encode(base64WireTransaction);
|
|
39
|
+
const { signatures } = decoder.decode(transactionBytes);
|
|
40
|
+
|
|
41
|
+
const signature = signatures[signerAddress];
|
|
42
|
+
if (!signature) {
|
|
43
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
44
|
+
address: signerAddress,
|
|
45
|
+
message: `No signature found for address ${signerAddress}`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return createSignatureDictionary({
|
|
50
|
+
signature,
|
|
51
|
+
signerAddress,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface CreateSignatureDictionaryArgs {
|
|
56
|
+
signature: SignatureBytes;
|
|
57
|
+
signerAddress: Address;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Creates a signature dictionary from a signature and signer address.
|
|
62
|
+
* @param signature - The signature to create the dictionary from
|
|
63
|
+
* @param signerAddress - The address of the signer whose signature to create the dictionary from
|
|
64
|
+
* @returns SignatureDictionary with only the specified signer's signature
|
|
65
|
+
* @throws {SignerError} If no signature is found for the given address
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const sigDict = createSignatureDictionary({ signature, signerAddress });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function createSignatureDictionary({
|
|
73
|
+
signature,
|
|
74
|
+
signerAddress,
|
|
75
|
+
}: CreateSignatureDictionaryArgs): SignatureDictionary {
|
|
76
|
+
assertIsAddress(signerAddress);
|
|
77
|
+
if (!signature) {
|
|
78
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
79
|
+
address: signerAddress,
|
|
80
|
+
message: `No signature found for address ${signerAddress}`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return Object.freeze({ [signerAddress]: signature });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Checks if the given value is a SolanaSigner.
|
|
88
|
+
* @param value - The value to check
|
|
89
|
+
* @returns True if the value is a SolanaSigner, false otherwise
|
|
90
|
+
*/
|
|
91
|
+
export function isSolanaSigner<TAddress extends string>(value: {
|
|
92
|
+
address: Address<TAddress>;
|
|
93
|
+
}): value is SolanaSigner<TAddress> {
|
|
94
|
+
return (
|
|
95
|
+
'address' in value &&
|
|
96
|
+
'isAvailable' in value &&
|
|
97
|
+
isMessagePartialSigner(value) &&
|
|
98
|
+
isTransactionPartialSigner(value)
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Asserts that the given value is a SolanaSigner, throwing an error if it is not.
|
|
104
|
+
* @param value - The value to check
|
|
105
|
+
* @throws {SignerError} If the value is not a SolanaSigner
|
|
106
|
+
*/
|
|
107
|
+
export function assertIsSolanaSigner<TAddress extends string>(value: {
|
|
108
|
+
address: Address<TAddress>;
|
|
109
|
+
}): asserts value is SolanaSigner<TAddress> {
|
|
110
|
+
if (!isSolanaSigner(value)) {
|
|
111
|
+
throwSignerError(SignerErrorCode.EXPECTED_SOLANA_SIGNER, {
|
|
112
|
+
address: value.address,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = {};
|