near-kit 0.0.0 → 0.2.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/LICENSE +21 -0
- package/README.md +473 -2
- package/dist/contracts/contract.d.ts +63 -0
- package/dist/contracts/contract.d.ts.map +1 -0
- package/dist/contracts/contract.js +42 -0
- package/dist/contracts/contract.js.map +1 -0
- package/dist/contracts/index.d.ts +5 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +5 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/core/actions.d.ts +193 -0
- package/dist/core/actions.d.ts.map +1 -0
- package/dist/core/actions.js +195 -0
- package/dist/core/actions.js.map +1 -0
- package/dist/core/config-schemas.d.ts +179 -0
- package/dist/core/config-schemas.d.ts.map +1 -0
- package/dist/core/config-schemas.js +169 -0
- package/dist/core/config-schemas.js.map +1 -0
- package/dist/core/constants.d.ts +43 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +49 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/near.d.ts +301 -0
- package/dist/core/near.d.ts.map +1 -0
- package/dist/core/near.js +504 -0
- package/dist/core/near.js.map +1 -0
- package/dist/core/nonce-manager.d.ts +39 -0
- package/dist/core/nonce-manager.d.ts.map +1 -0
- package/dist/core/nonce-manager.js +73 -0
- package/dist/core/nonce-manager.js.map +1 -0
- package/dist/core/rpc/rpc-error-handler.d.ts +60 -0
- package/dist/core/rpc/rpc-error-handler.d.ts.map +1 -0
- package/dist/core/rpc/rpc-error-handler.js +324 -0
- package/dist/core/rpc/rpc-error-handler.js.map +1 -0
- package/dist/core/rpc/rpc-schemas.d.ts +1812 -0
- package/dist/core/rpc/rpc-schemas.d.ts.map +1 -0
- package/dist/core/rpc/rpc-schemas.js +424 -0
- package/dist/core/rpc/rpc-schemas.js.map +1 -0
- package/dist/core/rpc/rpc.d.ts +117 -0
- package/dist/core/rpc/rpc.d.ts.map +1 -0
- package/dist/core/rpc/rpc.js +325 -0
- package/dist/core/rpc/rpc.js.map +1 -0
- package/dist/core/schema.d.ts +1188 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +396 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/transaction.d.ts +390 -0
- package/dist/core/transaction.d.ts.map +1 -0
- package/dist/core/transaction.js +653 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/core/types.d.ts +271 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/errors/index.d.ts +226 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +366 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/keys/credential-schemas.d.ts +98 -0
- package/dist/keys/credential-schemas.d.ts.map +1 -0
- package/dist/keys/credential-schemas.js +128 -0
- package/dist/keys/credential-schemas.js.map +1 -0
- package/dist/keys/file-keystore.d.ts +130 -0
- package/dist/keys/file-keystore.d.ts.map +1 -0
- package/dist/keys/file-keystore.js +266 -0
- package/dist/keys/file-keystore.js.map +1 -0
- package/dist/keys/in-memory-keystore.d.ts +71 -0
- package/dist/keys/in-memory-keystore.d.ts.map +1 -0
- package/dist/keys/in-memory-keystore.js +85 -0
- package/dist/keys/in-memory-keystore.js.map +1 -0
- package/dist/keys/index.d.ts +14 -0
- package/dist/keys/index.d.ts.map +1 -0
- package/dist/keys/index.js +20 -0
- package/dist/keys/index.js.map +1 -0
- package/dist/keys/native-keystore.d.ts +111 -0
- package/dist/keys/native-keystore.d.ts.map +1 -0
- package/dist/keys/native-keystore.js +167 -0
- package/dist/keys/native-keystore.js.map +1 -0
- package/dist/keys/rotating-keystore.d.ts +207 -0
- package/dist/keys/rotating-keystore.d.ts.map +1 -0
- package/dist/keys/rotating-keystore.js +240 -0
- package/dist/keys/rotating-keystore.js.map +1 -0
- package/dist/sandbox/index.d.ts +6 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/sandbox.d.ts +55 -0
- package/dist/sandbox/sandbox.d.ts.map +1 -0
- package/dist/sandbox/sandbox.js +341 -0
- package/dist/sandbox/sandbox.js.map +1 -0
- package/dist/utils/amount.d.ts +76 -0
- package/dist/utils/amount.d.ts.map +1 -0
- package/dist/utils/amount.js +137 -0
- package/dist/utils/amount.js.map +1 -0
- package/dist/utils/gas.d.ts +69 -0
- package/dist/utils/gas.d.ts.map +1 -0
- package/dist/utils/gas.js +92 -0
- package/dist/utils/gas.js.map +1 -0
- package/dist/utils/index.d.ts +14 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +14 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/key.d.ts +117 -0
- package/dist/utils/key.d.ts.map +1 -0
- package/dist/utils/key.js +270 -0
- package/dist/utils/key.js.map +1 -0
- package/dist/utils/nep413.d.ts +97 -0
- package/dist/utils/nep413.d.ts.map +1 -0
- package/dist/utils/nep413.js +154 -0
- package/dist/utils/nep413.js.map +1 -0
- package/dist/utils/validation.d.ts +114 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +150 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/wallets/adapters.d.ts +119 -0
- package/dist/wallets/adapters.d.ts.map +1 -0
- package/dist/wallets/adapters.js +267 -0
- package/dist/wallets/adapters.js.map +1 -0
- package/dist/wallets/index.d.ts +11 -0
- package/dist/wallets/index.d.ts.map +1 -0
- package/dist/wallets/index.js +2 -0
- package/dist/wallets/index.js.map +1 -0
- package/dist/wallets/types.d.ts +99 -0
- package/dist/wallets/types.d.ts.map +1 -0
- package/dist/wallets/types.js +10 -0
- package/dist/wallets/types.js.map +1 -0
- package/package.json +78 -7
- package/index.js +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native OS keystore implementation using system credential storage
|
|
3
|
+
*/
|
|
4
|
+
import type { KeyPair, KeyStore } from "../core/types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Native OS keystore using system credential storage
|
|
7
|
+
*
|
|
8
|
+
* This keystore uses the operating system's native secure credential storage:
|
|
9
|
+
* - **macOS**: Keychain Access
|
|
10
|
+
* - **Windows**: Credential Manager (DPAPI)
|
|
11
|
+
* - **Linux**: libsecret/Secret Service API
|
|
12
|
+
*
|
|
13
|
+
* ## Security Benefits
|
|
14
|
+
* - Keys stored in OS-level secure storage (not plain files)
|
|
15
|
+
* - Encrypted by OS using hardware-backed keys when available
|
|
16
|
+
* - Protected by user's system password/biometrics
|
|
17
|
+
* - Isolated from other applications
|
|
18
|
+
*
|
|
19
|
+
* ## Requirements
|
|
20
|
+
* - Requires `@napi-rs/keyring` native dependency
|
|
21
|
+
* - Linux requires `libsecret` (`apt install libsecret-1-dev` on Debian/Ubuntu)
|
|
22
|
+
*
|
|
23
|
+
* ## Limitations
|
|
24
|
+
* - Not available in browser environments (use InMemoryKeyStore instead)
|
|
25
|
+
* - Requires user to be logged in to the system
|
|
26
|
+
* - Keys are machine-specific (not synced across devices)
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Use OS keyring for maximum security
|
|
31
|
+
* const keyStore = new NativeKeyStore()
|
|
32
|
+
* const near = new Near({ keyStore })
|
|
33
|
+
*
|
|
34
|
+
* // Keys stored in:
|
|
35
|
+
* // - macOS: Keychain Access > "NEAR Credentials"
|
|
36
|
+
* // - Windows: Credential Manager > Generic Credentials
|
|
37
|
+
* // - Linux: GNOME Keyring / KDE Wallet
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class NativeKeyStore implements KeyStore {
|
|
41
|
+
private readonly service;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new native OS keystore
|
|
44
|
+
*
|
|
45
|
+
* @param service - Service name for credential storage (default: "NEAR Credentials")
|
|
46
|
+
* This appears in Keychain Access (macOS) or Credential Manager (Windows)
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // Default service name
|
|
51
|
+
* const keyStore = new NativeKeyStore()
|
|
52
|
+
*
|
|
53
|
+
* // Custom service name for your app
|
|
54
|
+
* const keyStore = new NativeKeyStore("MyApp NEAR Keys")
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
constructor(service?: string);
|
|
58
|
+
/**
|
|
59
|
+
* Create an Entry instance for keyring operations
|
|
60
|
+
*/
|
|
61
|
+
private getEntry;
|
|
62
|
+
/**
|
|
63
|
+
* Add a key to the OS keystore
|
|
64
|
+
*
|
|
65
|
+
* Stores the key securely in the operating system's credential storage.
|
|
66
|
+
* The key is encrypted by the OS and protected by the user's system password.
|
|
67
|
+
*
|
|
68
|
+
* @param accountId - NEAR account ID (used as credential name)
|
|
69
|
+
* @param key - Key pair to store
|
|
70
|
+
* @param options - Optional metadata (stored alongside the key in OS keyring)
|
|
71
|
+
*
|
|
72
|
+
* @throws {Error} If keyring access fails (e.g., user denies permission)
|
|
73
|
+
*/
|
|
74
|
+
add(accountId: string, key: KeyPair, options?: {
|
|
75
|
+
seedPhrase?: string;
|
|
76
|
+
derivationPath?: string;
|
|
77
|
+
implicitAccountId?: string;
|
|
78
|
+
}): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Get a key from the OS keystore
|
|
81
|
+
*
|
|
82
|
+
* Retrieves and decrypts the key from the operating system's credential storage.
|
|
83
|
+
*
|
|
84
|
+
* @param accountId - NEAR account ID
|
|
85
|
+
* @returns Key pair if found, null otherwise
|
|
86
|
+
*
|
|
87
|
+
* @throws {Error} If keyring access fails or key is corrupted
|
|
88
|
+
*/
|
|
89
|
+
get(accountId: string): Promise<KeyPair | null>;
|
|
90
|
+
/**
|
|
91
|
+
* Remove a key from the OS keystore
|
|
92
|
+
*
|
|
93
|
+
* Permanently deletes the credential from the operating system's storage.
|
|
94
|
+
*
|
|
95
|
+
* @param accountId - NEAR account ID
|
|
96
|
+
*/
|
|
97
|
+
remove(accountId: string): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* List all account IDs in the OS keystore
|
|
100
|
+
*
|
|
101
|
+
* ⚠️ **Note**: The underlying keyring library doesn't support listing all
|
|
102
|
+
* credentials for a service. This method returns an empty array.
|
|
103
|
+
*
|
|
104
|
+
* If you need to track multiple accounts, maintain a list separately
|
|
105
|
+
* (e.g., in a config file) and use this keystore only for secure key storage.
|
|
106
|
+
*
|
|
107
|
+
* @returns Empty array (OS keyrings don't support enumeration for security)
|
|
108
|
+
*/
|
|
109
|
+
list(): Promise<string[]>;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=native-keystore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-keystore.d.ts","sourceRoot":"","sources":["../../src/keys/native-keystore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAOzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,cAAe,YAAW,QAAQ;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAEhC;;;;;;;;;;;;;;OAcG;gBACS,OAAO,SAAqB;IAIxC;;OAEG;YACW,QAAQ;IAMtB;;;;;;;;;;;OAWG;IACG,GAAG,CACP,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAC3B,GACA,OAAO,CAAC,IAAI,CAAC;IAyBhB;;;;;;;;;OASG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAqBrD;;;;;;OAMG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9C;;;;;;;;;;OAUG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAKhC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native OS keystore implementation using system credential storage
|
|
3
|
+
*/
|
|
4
|
+
import { parseKey } from "../utils/key.js";
|
|
5
|
+
import { parseCredentialFile, } from "./credential-schemas.js";
|
|
6
|
+
/**
|
|
7
|
+
* Native OS keystore using system credential storage
|
|
8
|
+
*
|
|
9
|
+
* This keystore uses the operating system's native secure credential storage:
|
|
10
|
+
* - **macOS**: Keychain Access
|
|
11
|
+
* - **Windows**: Credential Manager (DPAPI)
|
|
12
|
+
* - **Linux**: libsecret/Secret Service API
|
|
13
|
+
*
|
|
14
|
+
* ## Security Benefits
|
|
15
|
+
* - Keys stored in OS-level secure storage (not plain files)
|
|
16
|
+
* - Encrypted by OS using hardware-backed keys when available
|
|
17
|
+
* - Protected by user's system password/biometrics
|
|
18
|
+
* - Isolated from other applications
|
|
19
|
+
*
|
|
20
|
+
* ## Requirements
|
|
21
|
+
* - Requires `@napi-rs/keyring` native dependency
|
|
22
|
+
* - Linux requires `libsecret` (`apt install libsecret-1-dev` on Debian/Ubuntu)
|
|
23
|
+
*
|
|
24
|
+
* ## Limitations
|
|
25
|
+
* - Not available in browser environments (use InMemoryKeyStore instead)
|
|
26
|
+
* - Requires user to be logged in to the system
|
|
27
|
+
* - Keys are machine-specific (not synced across devices)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Use OS keyring for maximum security
|
|
32
|
+
* const keyStore = new NativeKeyStore()
|
|
33
|
+
* const near = new Near({ keyStore })
|
|
34
|
+
*
|
|
35
|
+
* // Keys stored in:
|
|
36
|
+
* // - macOS: Keychain Access > "NEAR Credentials"
|
|
37
|
+
* // - Windows: Credential Manager > Generic Credentials
|
|
38
|
+
* // - Linux: GNOME Keyring / KDE Wallet
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class NativeKeyStore {
|
|
42
|
+
/**
|
|
43
|
+
* Create a new native OS keystore
|
|
44
|
+
*
|
|
45
|
+
* @param service - Service name for credential storage (default: "NEAR Credentials")
|
|
46
|
+
* This appears in Keychain Access (macOS) or Credential Manager (Windows)
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // Default service name
|
|
51
|
+
* const keyStore = new NativeKeyStore()
|
|
52
|
+
*
|
|
53
|
+
* // Custom service name for your app
|
|
54
|
+
* const keyStore = new NativeKeyStore("MyApp NEAR Keys")
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
constructor(service = "NEAR Credentials") {
|
|
58
|
+
this.service = service;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create an Entry instance for keyring operations
|
|
62
|
+
*/
|
|
63
|
+
async getEntry(accountId) {
|
|
64
|
+
// Dynamic import to allow graceful fallback if not installed
|
|
65
|
+
const { Entry } = await import("@napi-rs/keyring");
|
|
66
|
+
return new Entry(this.service, accountId);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Add a key to the OS keystore
|
|
70
|
+
*
|
|
71
|
+
* Stores the key securely in the operating system's credential storage.
|
|
72
|
+
* The key is encrypted by the OS and protected by the user's system password.
|
|
73
|
+
*
|
|
74
|
+
* @param accountId - NEAR account ID (used as credential name)
|
|
75
|
+
* @param key - Key pair to store
|
|
76
|
+
* @param options - Optional metadata (stored alongside the key in OS keyring)
|
|
77
|
+
*
|
|
78
|
+
* @throws {Error} If keyring access fails (e.g., user denies permission)
|
|
79
|
+
*/
|
|
80
|
+
async add(accountId, key, options) {
|
|
81
|
+
const entry = await this.getEntry(accountId);
|
|
82
|
+
// Store full key data as JSON
|
|
83
|
+
const keyData = {
|
|
84
|
+
account_id: accountId,
|
|
85
|
+
public_key: key.publicKey.toString(),
|
|
86
|
+
private_key: key.secretKey,
|
|
87
|
+
};
|
|
88
|
+
// Add optional fields if provided
|
|
89
|
+
if (options?.seedPhrase) {
|
|
90
|
+
keyData.master_seed_phrase = options.seedPhrase;
|
|
91
|
+
}
|
|
92
|
+
if (options?.derivationPath) {
|
|
93
|
+
keyData.seed_phrase_hd_path = options.derivationPath;
|
|
94
|
+
}
|
|
95
|
+
if (options?.implicitAccountId) {
|
|
96
|
+
keyData.implicit_account_id = options.implicitAccountId;
|
|
97
|
+
}
|
|
98
|
+
// Store as JSON string in keyring
|
|
99
|
+
entry.setPassword(JSON.stringify(keyData));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get a key from the OS keystore
|
|
103
|
+
*
|
|
104
|
+
* Retrieves and decrypts the key from the operating system's credential storage.
|
|
105
|
+
*
|
|
106
|
+
* @param accountId - NEAR account ID
|
|
107
|
+
* @returns Key pair if found, null otherwise
|
|
108
|
+
*
|
|
109
|
+
* @throws {Error} If keyring access fails or key is corrupted
|
|
110
|
+
*/
|
|
111
|
+
async get(accountId) {
|
|
112
|
+
try {
|
|
113
|
+
const entry = await this.getEntry(accountId);
|
|
114
|
+
const stored = entry.getPassword();
|
|
115
|
+
if (!stored) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
// Parse stored JSON data
|
|
119
|
+
const keyData = parseCredentialFile(JSON.parse(stored));
|
|
120
|
+
return parseKey(keyData.private_key);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
// Key not found or access denied
|
|
124
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Remove a key from the OS keystore
|
|
132
|
+
*
|
|
133
|
+
* Permanently deletes the credential from the operating system's storage.
|
|
134
|
+
*
|
|
135
|
+
* @param accountId - NEAR account ID
|
|
136
|
+
*/
|
|
137
|
+
async remove(accountId) {
|
|
138
|
+
try {
|
|
139
|
+
const entry = await this.getEntry(accountId);
|
|
140
|
+
entry.deletePassword();
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
// Ignore if credential doesn't exist
|
|
144
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* List all account IDs in the OS keystore
|
|
152
|
+
*
|
|
153
|
+
* ⚠️ **Note**: The underlying keyring library doesn't support listing all
|
|
154
|
+
* credentials for a service. This method returns an empty array.
|
|
155
|
+
*
|
|
156
|
+
* If you need to track multiple accounts, maintain a list separately
|
|
157
|
+
* (e.g., in a config file) and use this keystore only for secure key storage.
|
|
158
|
+
*
|
|
159
|
+
* @returns Empty array (OS keyrings don't support enumeration for security)
|
|
160
|
+
*/
|
|
161
|
+
async list() {
|
|
162
|
+
// Native keyrings don't support listing credentials for security reasons
|
|
163
|
+
// Applications should track account IDs separately if needed
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=native-keystore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-keystore.js","sourceRoot":"","sources":["../../src/keys/native-keystore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rotating key store implementation for concurrent transaction handling.
|
|
3
|
+
*/
|
|
4
|
+
import type { KeyPair, KeyStore } from "../core/types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Rotating key store that cycles through multiple keys per account.
|
|
7
|
+
*
|
|
8
|
+
* This keystore enables high-throughput concurrent transactions by rotating
|
|
9
|
+
* through multiple access keys for a single account. Each transaction uses
|
|
10
|
+
* a different key in round-robin fashion, eliminating nonce collisions.
|
|
11
|
+
*
|
|
12
|
+
* ## Use Cases
|
|
13
|
+
* - **High-throughput applications**: Send many concurrent transactions without nonce collisions
|
|
14
|
+
* - **Load balancing**: Distribute transaction load across multiple access keys
|
|
15
|
+
* - **Key rotation**: Seamlessly rotate keys without downtime
|
|
16
|
+
*
|
|
17
|
+
* ## How It Works
|
|
18
|
+
* - Each account can have multiple keys registered
|
|
19
|
+
* - `get()` returns the next key in round-robin order
|
|
20
|
+
* - Each key has independent nonce tracking via NonceManager
|
|
21
|
+
* - No nonce collisions between concurrent transactions
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Create keystore with multiple keys for one account
|
|
26
|
+
* const keyStore = new RotatingKeyStore()
|
|
27
|
+
* await keyStore.add("alice.near", parseKey("ed25519:key1..."))
|
|
28
|
+
* await keyStore.add("alice.near", parseKey("ed25519:key2..."))
|
|
29
|
+
* await keyStore.add("alice.near", parseKey("ed25519:key3..."))
|
|
30
|
+
*
|
|
31
|
+
* const near = new Near({ network: "testnet", keyStore })
|
|
32
|
+
*
|
|
33
|
+
* // Send 100 concurrent transactions - no nonce collisions!
|
|
34
|
+
* await Promise.all(
|
|
35
|
+
* Array(100).fill(0).map(() =>
|
|
36
|
+
* near.transaction("alice.near")
|
|
37
|
+
* .transfer("bob.near", "0.1")
|
|
38
|
+
* .send()
|
|
39
|
+
* )
|
|
40
|
+
* )
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* // Initialize with keys
|
|
46
|
+
* const keyStore = new RotatingKeyStore({
|
|
47
|
+
* "alice.near": [
|
|
48
|
+
* "ed25519:key1...",
|
|
49
|
+
* "ed25519:key2...",
|
|
50
|
+
* "ed25519:key3..."
|
|
51
|
+
* ]
|
|
52
|
+
* })
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* // Query rotation state
|
|
58
|
+
* const keys = await keyStore.getAll("alice.near")
|
|
59
|
+
* console.log(`Account has ${keys.length} keys`)
|
|
60
|
+
*
|
|
61
|
+
* const index = keyStore.getCurrentIndex("alice.near")
|
|
62
|
+
* console.log(`Currently at key index ${index}`)
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare class RotatingKeyStore implements KeyStore {
|
|
66
|
+
private keys;
|
|
67
|
+
private counters;
|
|
68
|
+
/**
|
|
69
|
+
* Create a new rotating keystore.
|
|
70
|
+
*
|
|
71
|
+
* @param initialKeys - Optional initial keys to populate the store.
|
|
72
|
+
* Maps account IDs to arrays of private key strings.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const keyStore = new RotatingKeyStore({
|
|
77
|
+
* "alice.near": ["ed25519:key1...", "ed25519:key2..."],
|
|
78
|
+
* "bob.near": ["ed25519:key3..."]
|
|
79
|
+
* })
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
constructor(initialKeys?: Record<string, string[]>);
|
|
83
|
+
/**
|
|
84
|
+
* Get the next key for an account using round-robin rotation.
|
|
85
|
+
*
|
|
86
|
+
* Each call to `get()` advances to the next key in the rotation.
|
|
87
|
+
* This is the core mechanism that enables concurrent transactions
|
|
88
|
+
* without nonce collisions.
|
|
89
|
+
*
|
|
90
|
+
* @param accountId - NEAR account ID
|
|
91
|
+
* @returns Next key in rotation, or null if no keys exist for account
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // First call returns key1, second returns key2, third returns key3, fourth returns key1...
|
|
96
|
+
* const key1 = await keyStore.get("alice.near")
|
|
97
|
+
* const key2 = await keyStore.get("alice.near")
|
|
98
|
+
* const key3 = await keyStore.get("alice.near")
|
|
99
|
+
* const key4 = await keyStore.get("alice.near") // Back to key1
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
get(accountId: string): Promise<KeyPair | null>;
|
|
103
|
+
/**
|
|
104
|
+
* Add a key to an account's rotation pool.
|
|
105
|
+
*
|
|
106
|
+
* If the account already has keys, the new key is appended to the rotation.
|
|
107
|
+
* If this is the first key for the account, it becomes the starting key.
|
|
108
|
+
*
|
|
109
|
+
* @param accountId - NEAR account ID
|
|
110
|
+
* @param key - Key pair to add to rotation
|
|
111
|
+
* @param options - Optional metadata (preserved but not used for rotation)
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* await keyStore.add("alice.near", keyPair1)
|
|
116
|
+
* await keyStore.add("alice.near", keyPair2) // Now rotates between both
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
add(accountId: string, key: KeyPair, _options?: {
|
|
120
|
+
seedPhrase?: string;
|
|
121
|
+
derivationPath?: string;
|
|
122
|
+
implicitAccountId?: string;
|
|
123
|
+
}): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Remove all keys for an account from the rotation pool.
|
|
126
|
+
*
|
|
127
|
+
* This also resets the rotation counter for the account.
|
|
128
|
+
*
|
|
129
|
+
* @param accountId - NEAR account ID
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* await keyStore.remove("alice.near")
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
remove(accountId: string): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* List all account IDs in the keystore.
|
|
139
|
+
*
|
|
140
|
+
* @returns Array of account IDs that have at least one key
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* const accounts = await keyStore.list()
|
|
145
|
+
* console.log(`Managing keys for: ${accounts.join(", ")}`)
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
list(): Promise<string[]>;
|
|
149
|
+
/**
|
|
150
|
+
* Get all keys for an account (non-rotating).
|
|
151
|
+
*
|
|
152
|
+
* Returns all keys in the rotation pool without advancing the counter.
|
|
153
|
+
* Useful for inspecting or managing the key pool.
|
|
154
|
+
*
|
|
155
|
+
* @param accountId - NEAR account ID
|
|
156
|
+
* @returns Array of all key pairs for the account, or empty array if none exist
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const keys = await keyStore.getAll("alice.near")
|
|
161
|
+
* console.log(`Account has ${keys.length} keys in rotation`)
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
getAll(accountId: string): Promise<KeyPair[]>;
|
|
165
|
+
/**
|
|
166
|
+
* Get the current rotation index for an account.
|
|
167
|
+
*
|
|
168
|
+
* The index indicates which key will be returned on the next `get()` call.
|
|
169
|
+
*
|
|
170
|
+
* @param accountId - NEAR account ID
|
|
171
|
+
* @returns Current counter value (0-based index into key array)
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* const index = keyStore.getCurrentIndex("alice.near")
|
|
176
|
+
* const totalKeys = (await keyStore.getAll("alice.near")).length
|
|
177
|
+
* console.log(`Next key: ${index % totalKeys}`)
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
getCurrentIndex(accountId: string): number;
|
|
181
|
+
/**
|
|
182
|
+
* Reset the rotation counter for an account.
|
|
183
|
+
*
|
|
184
|
+
* The next `get()` call will return the first key in the rotation.
|
|
185
|
+
*
|
|
186
|
+
* @param accountId - NEAR account ID
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* keyStore.resetCounter("alice.near")
|
|
191
|
+
* const key = await keyStore.get("alice.near") // Returns first key
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
resetCounter(accountId: string): void;
|
|
195
|
+
/**
|
|
196
|
+
* Clear all keys and counters from the keystore.
|
|
197
|
+
*
|
|
198
|
+
* Useful for testing cleanup or resetting state.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* keyStore.clear()
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
clear(): void;
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=rotating-keystore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotating-keystore.d.ts","sourceRoot":"","sources":["../../src/keys/rotating-keystore.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,QAAQ,CAAqB;IAErC;;;;;;;;;;;;;OAaG;gBACS,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAgBlD;;;;;;;;;;;;;;;;;;OAkBG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAerD;;;;;;;;;;;;;;;OAeG;IACG,GAAG,CACP,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAC3B,GACA,OAAO,CAAC,IAAI,CAAC;IAMhB;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C;;;;;;;;;;OAUG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/B;;;;;;;;;;;;;;OAcG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAInD;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI1C;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrC;;;;;;;;;OASG;IACH,KAAK,IAAI,IAAI;CAId"}
|