@phantom/indexed-db-stamper 0.1.4 → 1.0.0-beta.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/dist/index.d.ts CHANGED
@@ -25,8 +25,8 @@ declare class IndexedDbStamper implements StamperWithKeyManagement {
25
25
  private storeName;
26
26
  private keyName;
27
27
  private db;
28
- private keyInfo;
29
- private cryptoKeyPair;
28
+ private activeKeyPairRecord;
29
+ private pendingKeyPairRecord;
30
30
  algorithm: Algorithm;
31
31
  type: "PKI" | "OIDC";
32
32
  idToken?: string;
@@ -66,10 +66,23 @@ declare class IndexedDbStamper implements StamperWithKeyManagement {
66
66
  clear(): Promise<void>;
67
67
  private clearStoredKeys;
68
68
  private openDB;
69
- private generateAndStoreKeyPair;
70
- private storeKeyPair;
71
- private loadKeyPair;
72
- private getStoredKeyInfo;
69
+ /**
70
+ * Generate a new keypair for rotation without making it active
71
+ */
72
+ rotateKeyPair(): Promise<StamperKeyInfo>;
73
+ /**
74
+ * Switch to the pending keypair, making it active and cleaning up the old one
75
+ */
76
+ commitRotation(authenticatorId: string): Promise<void>;
77
+ /**
78
+ * Discard the pending keypair on rotation failure
79
+ */
80
+ rollbackRotation(): Promise<void>;
81
+ private generateAndStoreNewKeyPair;
82
+ private storeKeyPairRecord;
83
+ private loadActiveKeyPairRecord;
84
+ private loadPendingKeyPairRecord;
85
+ private removeKeyPairRecord;
73
86
  }
74
87
 
75
88
  export { IndexedDbStamper, IndexedDbStamperConfig };
package/dist/index.js CHANGED
@@ -40,8 +40,8 @@ var IndexedDbStamper = class {
40
40
  // Optional for PKI, required for OIDC
41
41
  constructor(config = {}) {
42
42
  this.db = null;
43
- this.keyInfo = null;
44
- this.cryptoKeyPair = null;
43
+ this.activeKeyPairRecord = null;
44
+ this.pendingKeyPairRecord = null;
45
45
  this.algorithm = import_sdk_types.Algorithm.ed25519;
46
46
  // Use Ed25519 for maximum security and performance
47
47
  // The type of stamper, can be changed at any time
@@ -61,29 +61,27 @@ var IndexedDbStamper = class {
61
61
  */
62
62
  async init() {
63
63
  await this.openDB();
64
- let keyInfo = await this.getStoredKeyInfo();
65
- if (!keyInfo) {
66
- keyInfo = await this.generateAndStoreKeyPair();
67
- } else {
68
- await this.loadKeyPair();
64
+ this.activeKeyPairRecord = await this.loadActiveKeyPairRecord();
65
+ if (!this.activeKeyPairRecord) {
66
+ this.activeKeyPairRecord = await this.generateAndStoreNewKeyPair("active");
69
67
  }
70
- this.keyInfo = keyInfo;
71
- return keyInfo;
68
+ this.pendingKeyPairRecord = await this.loadPendingKeyPairRecord();
69
+ return this.activeKeyPairRecord.keyInfo;
72
70
  }
73
71
  /**
74
72
  * Get the public key information
75
73
  */
76
74
  getKeyInfo() {
77
- return this.keyInfo;
75
+ return this.activeKeyPairRecord?.keyInfo || null;
78
76
  }
79
77
  /**
80
78
  * Reset the key pair by generating a new one
81
79
  */
82
80
  async resetKeyPair() {
83
81
  await this.clearStoredKeys();
84
- const keyInfo = await this.generateAndStoreKeyPair();
85
- this.keyInfo = keyInfo;
86
- return keyInfo;
82
+ this.activeKeyPairRecord = await this.generateAndStoreNewKeyPair("active");
83
+ this.pendingKeyPairRecord = null;
84
+ return this.activeKeyPairRecord.keyInfo;
87
85
  }
88
86
  /**
89
87
  * Create X-Phantom-Stamp header value using stored private key
@@ -92,7 +90,7 @@ var IndexedDbStamper = class {
92
90
  */
93
91
  async stamp(params) {
94
92
  const { data } = params;
95
- if (!this.keyInfo || !this.cryptoKeyPair) {
93
+ if (!this.activeKeyPairRecord) {
96
94
  throw new Error("Stamper not initialized. Call init() first.");
97
95
  }
98
96
  const dataBytes = new Uint8Array(data);
@@ -101,7 +99,7 @@ var IndexedDbStamper = class {
101
99
  name: this.algorithm,
102
100
  hash: "SHA-256"
103
101
  },
104
- this.cryptoKeyPair.privateKey,
102
+ this.activeKeyPairRecord.keyPair.privateKey,
105
103
  dataBytes
106
104
  );
107
105
  const signatureBase64url = (0, import_base64url.base64urlEncode)(new Uint8Array(signature));
@@ -110,14 +108,14 @@ var IndexedDbStamper = class {
110
108
  const salt = params.type === "OIDC" ? params.salt : this.salt;
111
109
  const stampData = stampType === "PKI" ? {
112
110
  // Decode base58 public key to bytes, then encode as base64url (consistent with ApiKeyStamper)
113
- publicKey: (0, import_base64url.base64urlEncode)(import_bs58.default.decode(this.keyInfo.publicKey)),
111
+ publicKey: (0, import_base64url.base64urlEncode)(import_bs58.default.decode(this.activeKeyPairRecord.keyInfo.publicKey)),
114
112
  signature: signatureBase64url,
115
113
  kind: "PKI",
116
114
  algorithm: this.algorithm
117
115
  } : {
118
116
  kind: "OIDC",
119
117
  idToken,
120
- publicKey: (0, import_base64url.base64urlEncode)(import_bs58.default.decode(this.keyInfo.publicKey)),
118
+ publicKey: (0, import_base64url.base64urlEncode)(import_bs58.default.decode(this.activeKeyPairRecord.keyInfo.publicKey)),
121
119
  salt,
122
120
  algorithm: this.algorithm,
123
121
  signature: signatureBase64url
@@ -130,8 +128,8 @@ var IndexedDbStamper = class {
130
128
  */
131
129
  async clear() {
132
130
  await this.clearStoredKeys();
133
- this.keyInfo = null;
134
- this.cryptoKeyPair = null;
131
+ this.activeKeyPairRecord = null;
132
+ this.pendingKeyPairRecord = null;
135
133
  }
136
134
  async clearStoredKeys() {
137
135
  if (!this.db) {
@@ -140,8 +138,8 @@ var IndexedDbStamper = class {
140
138
  return new Promise((resolve, reject) => {
141
139
  const transaction = this.db.transaction([this.storeName], "readwrite");
142
140
  const store = transaction.objectStore(this.storeName);
143
- const deleteKeyPair = store.delete(`${this.keyName}-keypair`);
144
- const deleteKeyInfo = store.delete(`${this.keyName}-info`);
141
+ const deleteActiveKeyPair = store.delete(`${this.keyName}-active`);
142
+ const deletePendingKeyPair = store.delete(`${this.keyName}-pending`);
145
143
  let completed = 0;
146
144
  const total = 2;
147
145
  const checkComplete = () => {
@@ -150,10 +148,10 @@ var IndexedDbStamper = class {
150
148
  resolve();
151
149
  }
152
150
  };
153
- deleteKeyPair.onsuccess = checkComplete;
154
- deleteKeyInfo.onsuccess = checkComplete;
155
- deleteKeyPair.onerror = () => reject(deleteKeyPair.error);
156
- deleteKeyInfo.onerror = () => reject(deleteKeyInfo.error);
151
+ deleteActiveKeyPair.onsuccess = checkComplete;
152
+ deletePendingKeyPair.onsuccess = checkComplete;
153
+ deleteActiveKeyPair.onerror = () => reject(deleteActiveKeyPair.error);
154
+ deletePendingKeyPair.onerror = () => reject(deletePendingKeyPair.error);
157
155
  });
158
156
  }
159
157
  async openDB() {
@@ -172,8 +170,46 @@ var IndexedDbStamper = class {
172
170
  };
173
171
  });
174
172
  }
175
- async generateAndStoreKeyPair() {
176
- this.cryptoKeyPair = await crypto.subtle.generateKey(
173
+ /**
174
+ * Generate a new keypair for rotation without making it active
175
+ */
176
+ async rotateKeyPair() {
177
+ if (!this.db) {
178
+ await this.openDB();
179
+ }
180
+ this.pendingKeyPairRecord = await this.generateAndStoreNewKeyPair("pending");
181
+ return this.pendingKeyPairRecord.keyInfo;
182
+ }
183
+ /**
184
+ * Switch to the pending keypair, making it active and cleaning up the old one
185
+ */
186
+ async commitRotation(authenticatorId) {
187
+ if (!this.pendingKeyPairRecord) {
188
+ throw new Error("No pending keypair to commit");
189
+ }
190
+ if (this.activeKeyPairRecord) {
191
+ await this.removeKeyPairRecord("active");
192
+ }
193
+ this.pendingKeyPairRecord.status = "active";
194
+ this.pendingKeyPairRecord.authenticatorId = authenticatorId;
195
+ this.pendingKeyPairRecord.keyInfo.authenticatorId = authenticatorId;
196
+ this.activeKeyPairRecord = this.pendingKeyPairRecord;
197
+ this.pendingKeyPairRecord = null;
198
+ await this.storeKeyPairRecord(this.activeKeyPairRecord, "active");
199
+ await this.removeKeyPairRecord("pending");
200
+ }
201
+ /**
202
+ * Discard the pending keypair on rotation failure
203
+ */
204
+ async rollbackRotation() {
205
+ if (!this.pendingKeyPairRecord) {
206
+ return;
207
+ }
208
+ await this.removeKeyPairRecord("pending");
209
+ this.pendingKeyPairRecord = null;
210
+ }
211
+ async generateAndStoreNewKeyPair(type) {
212
+ const keyPair = await crypto.subtle.generateKey(
177
213
  {
178
214
  name: "Ed25519"
179
215
  },
@@ -181,65 +217,73 @@ var IndexedDbStamper = class {
181
217
  // non-extractable - private key can never be exported
182
218
  ["sign", "verify"]
183
219
  );
184
- const rawPublicKeyBuffer = await crypto.subtle.exportKey("raw", this.cryptoKeyPair.publicKey);
220
+ const rawPublicKeyBuffer = await crypto.subtle.exportKey("raw", keyPair.publicKey);
185
221
  const publicKeyBase58 = import_bs58.default.encode(new Uint8Array(rawPublicKeyBuffer));
186
222
  const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKeyBuffer);
187
223
  const keyId = (0, import_base64url.base64urlEncode)(new Uint8Array(keyIdBuffer)).substring(0, 16);
224
+ const now = Date.now();
188
225
  const keyInfo = {
189
226
  keyId,
190
- publicKey: publicKeyBase58
227
+ publicKey: publicKeyBase58,
228
+ createdAt: now
191
229
  };
192
- await this.storeKeyPair(this.cryptoKeyPair, keyInfo);
193
- return keyInfo;
230
+ const record = {
231
+ keyPair,
232
+ keyInfo,
233
+ createdAt: now,
234
+ expiresAt: 0,
235
+ // Not used anymore, kept for backward compatibility
236
+ status: type
237
+ };
238
+ await this.storeKeyPairRecord(record, type);
239
+ return record;
194
240
  }
195
- async storeKeyPair(keyPair, keyInfo) {
241
+ async storeKeyPairRecord(record, type) {
196
242
  if (!this.db) {
197
243
  throw new Error("Database not initialized");
198
244
  }
199
245
  return new Promise((resolve, reject) => {
200
246
  const transaction = this.db.transaction([this.storeName], "readwrite");
201
247
  const store = transaction.objectStore(this.storeName);
202
- const keyPairRequest = store.put(keyPair, `${this.keyName}-keypair`);
203
- const keyInfoRequest = store.put(keyInfo, `${this.keyName}-info`);
204
- let completed = 0;
205
- const total = 2;
206
- const checkComplete = () => {
207
- completed++;
208
- if (completed === total) {
209
- resolve();
210
- }
211
- };
212
- keyPairRequest.onsuccess = checkComplete;
213
- keyInfoRequest.onsuccess = checkComplete;
214
- keyPairRequest.onerror = () => reject(keyPairRequest.error);
215
- keyInfoRequest.onerror = () => reject(keyInfoRequest.error);
248
+ const request = store.put(record, `${this.keyName}-${type}`);
249
+ request.onsuccess = () => resolve();
250
+ request.onerror = () => reject(request.error);
216
251
  });
217
252
  }
218
- async loadKeyPair() {
253
+ async loadActiveKeyPairRecord() {
219
254
  if (!this.db) {
220
- return;
255
+ return null;
221
256
  }
222
257
  return new Promise((resolve, reject) => {
223
258
  const transaction = this.db.transaction([this.storeName], "readonly");
224
259
  const store = transaction.objectStore(this.storeName);
225
- const request = store.get(`${this.keyName}-keypair`);
226
- request.onsuccess = () => {
227
- this.cryptoKeyPair = request.result || null;
228
- resolve();
229
- };
260
+ const request = store.get(`${this.keyName}-active`);
261
+ request.onsuccess = () => resolve(request.result || null);
230
262
  request.onerror = () => reject(request.error);
231
263
  });
232
264
  }
233
- async getStoredKeyInfo() {
265
+ async loadPendingKeyPairRecord() {
234
266
  if (!this.db) {
235
267
  return null;
236
268
  }
237
269
  return new Promise((resolve, reject) => {
238
270
  const transaction = this.db.transaction([this.storeName], "readonly");
239
271
  const store = transaction.objectStore(this.storeName);
240
- const request = store.get(`${this.keyName}-info`);
272
+ const request = store.get(`${this.keyName}-pending`);
241
273
  request.onsuccess = () => resolve(request.result || null);
242
274
  request.onerror = () => reject(request.error);
243
275
  });
244
276
  }
277
+ async removeKeyPairRecord(type) {
278
+ if (!this.db) {
279
+ return;
280
+ }
281
+ return new Promise((resolve, reject) => {
282
+ const transaction = this.db.transaction([this.storeName], "readwrite");
283
+ const store = transaction.objectStore(this.storeName);
284
+ const request = store.delete(`${this.keyName}-${type}`);
285
+ request.onsuccess = () => resolve();
286
+ request.onerror = () => reject(request.error);
287
+ });
288
+ }
245
289
  };
package/dist/index.mjs CHANGED
@@ -6,8 +6,8 @@ var IndexedDbStamper = class {
6
6
  // Optional for PKI, required for OIDC
7
7
  constructor(config = {}) {
8
8
  this.db = null;
9
- this.keyInfo = null;
10
- this.cryptoKeyPair = null;
9
+ this.activeKeyPairRecord = null;
10
+ this.pendingKeyPairRecord = null;
11
11
  this.algorithm = Algorithm.ed25519;
12
12
  // Use Ed25519 for maximum security and performance
13
13
  // The type of stamper, can be changed at any time
@@ -27,29 +27,27 @@ var IndexedDbStamper = class {
27
27
  */
28
28
  async init() {
29
29
  await this.openDB();
30
- let keyInfo = await this.getStoredKeyInfo();
31
- if (!keyInfo) {
32
- keyInfo = await this.generateAndStoreKeyPair();
33
- } else {
34
- await this.loadKeyPair();
30
+ this.activeKeyPairRecord = await this.loadActiveKeyPairRecord();
31
+ if (!this.activeKeyPairRecord) {
32
+ this.activeKeyPairRecord = await this.generateAndStoreNewKeyPair("active");
35
33
  }
36
- this.keyInfo = keyInfo;
37
- return keyInfo;
34
+ this.pendingKeyPairRecord = await this.loadPendingKeyPairRecord();
35
+ return this.activeKeyPairRecord.keyInfo;
38
36
  }
39
37
  /**
40
38
  * Get the public key information
41
39
  */
42
40
  getKeyInfo() {
43
- return this.keyInfo;
41
+ return this.activeKeyPairRecord?.keyInfo || null;
44
42
  }
45
43
  /**
46
44
  * Reset the key pair by generating a new one
47
45
  */
48
46
  async resetKeyPair() {
49
47
  await this.clearStoredKeys();
50
- const keyInfo = await this.generateAndStoreKeyPair();
51
- this.keyInfo = keyInfo;
52
- return keyInfo;
48
+ this.activeKeyPairRecord = await this.generateAndStoreNewKeyPair("active");
49
+ this.pendingKeyPairRecord = null;
50
+ return this.activeKeyPairRecord.keyInfo;
53
51
  }
54
52
  /**
55
53
  * Create X-Phantom-Stamp header value using stored private key
@@ -58,7 +56,7 @@ var IndexedDbStamper = class {
58
56
  */
59
57
  async stamp(params) {
60
58
  const { data } = params;
61
- if (!this.keyInfo || !this.cryptoKeyPair) {
59
+ if (!this.activeKeyPairRecord) {
62
60
  throw new Error("Stamper not initialized. Call init() first.");
63
61
  }
64
62
  const dataBytes = new Uint8Array(data);
@@ -67,7 +65,7 @@ var IndexedDbStamper = class {
67
65
  name: this.algorithm,
68
66
  hash: "SHA-256"
69
67
  },
70
- this.cryptoKeyPair.privateKey,
68
+ this.activeKeyPairRecord.keyPair.privateKey,
71
69
  dataBytes
72
70
  );
73
71
  const signatureBase64url = base64urlEncode(new Uint8Array(signature));
@@ -76,14 +74,14 @@ var IndexedDbStamper = class {
76
74
  const salt = params.type === "OIDC" ? params.salt : this.salt;
77
75
  const stampData = stampType === "PKI" ? {
78
76
  // Decode base58 public key to bytes, then encode as base64url (consistent with ApiKeyStamper)
79
- publicKey: base64urlEncode(bs58.decode(this.keyInfo.publicKey)),
77
+ publicKey: base64urlEncode(bs58.decode(this.activeKeyPairRecord.keyInfo.publicKey)),
80
78
  signature: signatureBase64url,
81
79
  kind: "PKI",
82
80
  algorithm: this.algorithm
83
81
  } : {
84
82
  kind: "OIDC",
85
83
  idToken,
86
- publicKey: base64urlEncode(bs58.decode(this.keyInfo.publicKey)),
84
+ publicKey: base64urlEncode(bs58.decode(this.activeKeyPairRecord.keyInfo.publicKey)),
87
85
  salt,
88
86
  algorithm: this.algorithm,
89
87
  signature: signatureBase64url
@@ -96,8 +94,8 @@ var IndexedDbStamper = class {
96
94
  */
97
95
  async clear() {
98
96
  await this.clearStoredKeys();
99
- this.keyInfo = null;
100
- this.cryptoKeyPair = null;
97
+ this.activeKeyPairRecord = null;
98
+ this.pendingKeyPairRecord = null;
101
99
  }
102
100
  async clearStoredKeys() {
103
101
  if (!this.db) {
@@ -106,8 +104,8 @@ var IndexedDbStamper = class {
106
104
  return new Promise((resolve, reject) => {
107
105
  const transaction = this.db.transaction([this.storeName], "readwrite");
108
106
  const store = transaction.objectStore(this.storeName);
109
- const deleteKeyPair = store.delete(`${this.keyName}-keypair`);
110
- const deleteKeyInfo = store.delete(`${this.keyName}-info`);
107
+ const deleteActiveKeyPair = store.delete(`${this.keyName}-active`);
108
+ const deletePendingKeyPair = store.delete(`${this.keyName}-pending`);
111
109
  let completed = 0;
112
110
  const total = 2;
113
111
  const checkComplete = () => {
@@ -116,10 +114,10 @@ var IndexedDbStamper = class {
116
114
  resolve();
117
115
  }
118
116
  };
119
- deleteKeyPair.onsuccess = checkComplete;
120
- deleteKeyInfo.onsuccess = checkComplete;
121
- deleteKeyPair.onerror = () => reject(deleteKeyPair.error);
122
- deleteKeyInfo.onerror = () => reject(deleteKeyInfo.error);
117
+ deleteActiveKeyPair.onsuccess = checkComplete;
118
+ deletePendingKeyPair.onsuccess = checkComplete;
119
+ deleteActiveKeyPair.onerror = () => reject(deleteActiveKeyPair.error);
120
+ deletePendingKeyPair.onerror = () => reject(deletePendingKeyPair.error);
123
121
  });
124
122
  }
125
123
  async openDB() {
@@ -138,8 +136,46 @@ var IndexedDbStamper = class {
138
136
  };
139
137
  });
140
138
  }
141
- async generateAndStoreKeyPair() {
142
- this.cryptoKeyPair = await crypto.subtle.generateKey(
139
+ /**
140
+ * Generate a new keypair for rotation without making it active
141
+ */
142
+ async rotateKeyPair() {
143
+ if (!this.db) {
144
+ await this.openDB();
145
+ }
146
+ this.pendingKeyPairRecord = await this.generateAndStoreNewKeyPair("pending");
147
+ return this.pendingKeyPairRecord.keyInfo;
148
+ }
149
+ /**
150
+ * Switch to the pending keypair, making it active and cleaning up the old one
151
+ */
152
+ async commitRotation(authenticatorId) {
153
+ if (!this.pendingKeyPairRecord) {
154
+ throw new Error("No pending keypair to commit");
155
+ }
156
+ if (this.activeKeyPairRecord) {
157
+ await this.removeKeyPairRecord("active");
158
+ }
159
+ this.pendingKeyPairRecord.status = "active";
160
+ this.pendingKeyPairRecord.authenticatorId = authenticatorId;
161
+ this.pendingKeyPairRecord.keyInfo.authenticatorId = authenticatorId;
162
+ this.activeKeyPairRecord = this.pendingKeyPairRecord;
163
+ this.pendingKeyPairRecord = null;
164
+ await this.storeKeyPairRecord(this.activeKeyPairRecord, "active");
165
+ await this.removeKeyPairRecord("pending");
166
+ }
167
+ /**
168
+ * Discard the pending keypair on rotation failure
169
+ */
170
+ async rollbackRotation() {
171
+ if (!this.pendingKeyPairRecord) {
172
+ return;
173
+ }
174
+ await this.removeKeyPairRecord("pending");
175
+ this.pendingKeyPairRecord = null;
176
+ }
177
+ async generateAndStoreNewKeyPair(type) {
178
+ const keyPair = await crypto.subtle.generateKey(
143
179
  {
144
180
  name: "Ed25519"
145
181
  },
@@ -147,67 +183,75 @@ var IndexedDbStamper = class {
147
183
  // non-extractable - private key can never be exported
148
184
  ["sign", "verify"]
149
185
  );
150
- const rawPublicKeyBuffer = await crypto.subtle.exportKey("raw", this.cryptoKeyPair.publicKey);
186
+ const rawPublicKeyBuffer = await crypto.subtle.exportKey("raw", keyPair.publicKey);
151
187
  const publicKeyBase58 = bs58.encode(new Uint8Array(rawPublicKeyBuffer));
152
188
  const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKeyBuffer);
153
189
  const keyId = base64urlEncode(new Uint8Array(keyIdBuffer)).substring(0, 16);
190
+ const now = Date.now();
154
191
  const keyInfo = {
155
192
  keyId,
156
- publicKey: publicKeyBase58
193
+ publicKey: publicKeyBase58,
194
+ createdAt: now
157
195
  };
158
- await this.storeKeyPair(this.cryptoKeyPair, keyInfo);
159
- return keyInfo;
196
+ const record = {
197
+ keyPair,
198
+ keyInfo,
199
+ createdAt: now,
200
+ expiresAt: 0,
201
+ // Not used anymore, kept for backward compatibility
202
+ status: type
203
+ };
204
+ await this.storeKeyPairRecord(record, type);
205
+ return record;
160
206
  }
161
- async storeKeyPair(keyPair, keyInfo) {
207
+ async storeKeyPairRecord(record, type) {
162
208
  if (!this.db) {
163
209
  throw new Error("Database not initialized");
164
210
  }
165
211
  return new Promise((resolve, reject) => {
166
212
  const transaction = this.db.transaction([this.storeName], "readwrite");
167
213
  const store = transaction.objectStore(this.storeName);
168
- const keyPairRequest = store.put(keyPair, `${this.keyName}-keypair`);
169
- const keyInfoRequest = store.put(keyInfo, `${this.keyName}-info`);
170
- let completed = 0;
171
- const total = 2;
172
- const checkComplete = () => {
173
- completed++;
174
- if (completed === total) {
175
- resolve();
176
- }
177
- };
178
- keyPairRequest.onsuccess = checkComplete;
179
- keyInfoRequest.onsuccess = checkComplete;
180
- keyPairRequest.onerror = () => reject(keyPairRequest.error);
181
- keyInfoRequest.onerror = () => reject(keyInfoRequest.error);
214
+ const request = store.put(record, `${this.keyName}-${type}`);
215
+ request.onsuccess = () => resolve();
216
+ request.onerror = () => reject(request.error);
182
217
  });
183
218
  }
184
- async loadKeyPair() {
219
+ async loadActiveKeyPairRecord() {
185
220
  if (!this.db) {
186
- return;
221
+ return null;
187
222
  }
188
223
  return new Promise((resolve, reject) => {
189
224
  const transaction = this.db.transaction([this.storeName], "readonly");
190
225
  const store = transaction.objectStore(this.storeName);
191
- const request = store.get(`${this.keyName}-keypair`);
192
- request.onsuccess = () => {
193
- this.cryptoKeyPair = request.result || null;
194
- resolve();
195
- };
226
+ const request = store.get(`${this.keyName}-active`);
227
+ request.onsuccess = () => resolve(request.result || null);
196
228
  request.onerror = () => reject(request.error);
197
229
  });
198
230
  }
199
- async getStoredKeyInfo() {
231
+ async loadPendingKeyPairRecord() {
200
232
  if (!this.db) {
201
233
  return null;
202
234
  }
203
235
  return new Promise((resolve, reject) => {
204
236
  const transaction = this.db.transaction([this.storeName], "readonly");
205
237
  const store = transaction.objectStore(this.storeName);
206
- const request = store.get(`${this.keyName}-info`);
238
+ const request = store.get(`${this.keyName}-pending`);
207
239
  request.onsuccess = () => resolve(request.result || null);
208
240
  request.onerror = () => reject(request.error);
209
241
  });
210
242
  }
243
+ async removeKeyPairRecord(type) {
244
+ if (!this.db) {
245
+ return;
246
+ }
247
+ return new Promise((resolve, reject) => {
248
+ const transaction = this.db.transaction([this.storeName], "readwrite");
249
+ const store = transaction.objectStore(this.storeName);
250
+ const request = store.delete(`${this.keyName}-${type}`);
251
+ request.onsuccess = () => resolve();
252
+ request.onerror = () => reject(request.error);
253
+ });
254
+ }
211
255
  };
212
256
  export {
213
257
  IndexedDbStamper
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/indexed-db-stamper",
3
- "version": "0.1.4",
3
+ "version": "1.0.0-beta.0",
4
4
  "description": "IndexedDB stamper for Phantom Wallet SDK with non-extractable key storage",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -39,10 +39,10 @@
39
39
  "typescript": "^5.0.4"
40
40
  },
41
41
  "dependencies": {
42
- "@phantom/base64url": "^0.1.0",
43
- "@phantom/crypto": "^0.1.2",
44
- "@phantom/embedded-provider-core": "^0.1.5",
45
- "@phantom/sdk-types": "^0.1.4",
42
+ "@phantom/base64url": "^1.0.0-beta.0",
43
+ "@phantom/crypto": "^1.0.0-beta.0",
44
+ "@phantom/embedded-provider-core": "^1.0.0-beta.0",
45
+ "@phantom/sdk-types": "^1.0.0-beta.0",
46
46
  "bs58": "^6.0.0",
47
47
  "buffer": "^6.0.3"
48
48
  },