emblem-vault-ai-signers 0.1.0 → 0.1.2

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 CHANGED
@@ -4,6 +4,8 @@ Remote signer adapters for Emblem Vault that plug into popular Ethereum librarie
4
4
 
5
5
  - `toViemAccount()` – creates a viem `Account` that signs via Emblem
6
6
  - `toEthersWallet()` – creates an ethers v6 `Signer` that signs via Emblem
7
+ - Implements `initialize()`, `getVaultId()`, `setChainId()`, `getChainId()`
8
+ - Adds `signAndBroadcast(tx, waitForReceipt?)` helper (optional)
7
9
  - `toWeb3Adapter()` – returns a minimal Web3-style signer adapter (EVM)
8
10
  - `toSolanaWeb3Signer()` – returns a stub Solana signer with `publicKey`
9
11
  - `toSolanaKitSigner()` – returns a stub Solana signer with `publicKey`
@@ -39,7 +41,17 @@ const viemClient = createPublicClient({ chain: mainnet, transport: http() });
39
41
  // ethers v6
40
42
  const provider = new JsonRpcProvider(process.env.RPC_URL!);
41
43
  const wallet = await client.toEthersWallet(provider);
42
- // e.g. await wallet.sendTransaction({ to: "0x...", value: 1n })
44
+
45
+ // Read metadata
46
+ const addr = await wallet.getAddress();
47
+ const vaultId = wallet.getVaultId();
48
+
49
+ // Sign & send via ethers Provider
50
+ await wallet.signMessage("hello");
51
+ await wallet.sendTransaction({ to: "0x...", value: 1n });
52
+
53
+ // Or sign and broadcast, returning tx hash
54
+ const txHash = await wallet.signAndBroadcast({ to: "0x...", value: 1n }, true);
43
55
 
44
56
  // web3.js-like adapter (minimal)
45
57
  const web3Adapter = await client.toWeb3Adapter();
@@ -171,6 +183,13 @@ EmblemVaultClient#toEthersWallet(provider?): Promise<Signer>
171
183
  EmblemVaultClient#toWeb3Adapter(): Promise<{ address, signMessage, signTypedData, signTransaction }>
172
184
  EmblemVaultClient#toSolanaWeb3Signer(): Promise<{ publicKey }>
173
185
  EmblemVaultClient#toSolanaKitSigner(): Promise<{ publicKey }>
186
+
187
+ Ethers wallet (v6) adds:
188
+ - initialize(): Promise<void>
189
+ - getVaultId(): string
190
+ - setChainId(n: number): void
191
+ - getChainId(): number
192
+ - signAndBroadcast(tx: TransactionRequest, waitForReceipt?: boolean): Promise<string>
174
193
  ```
175
194
 
176
195
  Adapters POST to the Emblem API endpoints:
package/dist/ethers.d.ts CHANGED
@@ -1,15 +1,28 @@
1
1
  import type { EmblemRemoteConfig, VaultInfo } from "./types";
2
2
  import { AbstractSigner } from "ethers";
3
- import type { Provider, TransactionRequest, TransactionResponse, TypedDataDomain, TypedDataField } from "ethers";
3
+ import type { Provider, TransactionLike, TransactionRequest, TransactionResponse, TypedDataDomain, TypedDataField } from "ethers";
4
4
  export declare class EmblemEthersWallet extends AbstractSigner {
5
- #private;
6
- readonly address: `0x${string}`;
7
- constructor(address: `0x${string}`, vaultId: string, config: EmblemRemoteConfig, provider?: Provider | null);
5
+ private readonly _config;
6
+ private _address;
7
+ private _vaultId;
8
+ private _chainId;
9
+ constructor(config: EmblemRemoteConfig, provider?: Provider | null, seed?: {
10
+ address?: `0x${string}`;
11
+ vaultId?: string;
12
+ chainId?: number;
13
+ });
14
+ initialize(): Promise<void>;
8
15
  getAddress(): Promise<string>;
16
+ getVaultId(): string;
17
+ setChainId(chainId: number): void;
18
+ getChainId(): number;
9
19
  connect(provider: Provider): EmblemEthersWallet;
10
20
  signMessage(message: string | Uint8Array): Promise<string>;
11
21
  signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string>;
22
+ _signTypedData(domain: TypedDataDomain, types: Record<string, Array<TypedDataField>>, value: Record<string, any>): Promise<string>;
12
23
  signTransaction(tx: TransactionRequest): Promise<string>;
13
24
  sendTransaction(tx: TransactionRequest): Promise<TransactionResponse>;
25
+ populateTransaction(transaction: TransactionRequest): Promise<TransactionLike<string>>;
26
+ signAndBroadcast(transaction: TransactionRequest, waitForReceipt?: boolean): Promise<string>;
14
27
  }
15
28
  export declare function toEthersWallet(config: EmblemRemoteConfig, provider?: Provider | null, infoOverride?: VaultInfo): Promise<EmblemEthersWallet>;
package/dist/ethers.js CHANGED
@@ -1,71 +1,163 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _EmblemEthersWallet_config, _EmblemEthersWallet_vaultId;
13
1
  import { emblemPost } from "./http";
14
2
  import { bytesToHex, normalizeTxForEmblem } from "./utils";
15
3
  import { fetchVaultInfo } from "./vault";
16
- import { AbstractSigner, } from "ethers";
4
+ import { AbstractSigner, resolveAddress } from "ethers";
17
5
  export class EmblemEthersWallet extends AbstractSigner {
18
- constructor(address, vaultId, config, provider) {
6
+ constructor(config, provider, seed) {
19
7
  super(provider ?? null);
20
- _EmblemEthersWallet_config.set(this, void 0);
21
- _EmblemEthersWallet_vaultId.set(this, void 0);
22
- this.address = address;
23
- __classPrivateFieldSet(this, _EmblemEthersWallet_vaultId, vaultId, "f");
24
- __classPrivateFieldSet(this, _EmblemEthersWallet_config, config, "f");
8
+ this._address = null;
9
+ this._vaultId = null;
10
+ this._chainId = 1;
11
+ this._config = config;
12
+ if (seed?.address)
13
+ this._address = seed.address;
14
+ if (seed?.vaultId)
15
+ this._vaultId = seed.vaultId;
16
+ if (seed?.chainId)
17
+ this._chainId = seed.chainId;
18
+ }
19
+ async initialize() {
20
+ const info = await fetchVaultInfo(this._config);
21
+ this._address = info.evmAddress;
22
+ this._vaultId = info.vaultId;
25
23
  }
26
24
  async getAddress() {
27
- return this.address;
25
+ if (!this._address)
26
+ await this.initialize();
27
+ return this._address;
28
+ }
29
+ getVaultId() {
30
+ if (!this._vaultId)
31
+ throw new Error("Wallet not initialized. Call initialize() first.");
32
+ return this._vaultId;
33
+ }
34
+ setChainId(chainId) {
35
+ this._chainId = chainId;
36
+ }
37
+ getChainId() {
38
+ return this._chainId;
28
39
  }
29
40
  connect(provider) {
30
- return new EmblemEthersWallet(this.address, __classPrivateFieldGet(this, _EmblemEthersWallet_vaultId, "f"), __classPrivateFieldGet(this, _EmblemEthersWallet_config, "f"), provider);
41
+ if (!provider)
42
+ throw new Error("Provider cannot be null");
43
+ return new EmblemEthersWallet(this._config, provider, { address: this._address ?? undefined, vaultId: this._vaultId ?? undefined, chainId: this._chainId });
31
44
  }
32
45
  async signMessage(message) {
33
- const vaultId = __classPrivateFieldGet(this, _EmblemEthersWallet_vaultId, "f");
46
+ if (!this._vaultId)
47
+ await this.initialize();
34
48
  const payload = typeof message === "string" ? message : bytesToHex(message);
35
- const data = await emblemPost("/sign-eth-message", { vaultId, message: payload }, __classPrivateFieldGet(this, _EmblemEthersWallet_config, "f"));
49
+ const data = await emblemPost("/sign-eth-message", { vaultId: this._vaultId, message: payload }, this._config);
36
50
  return data.signature;
37
51
  }
38
52
  async signTypedData(domain, types, value) {
39
- const vaultId = __classPrivateFieldGet(this, _EmblemEthersWallet_vaultId, "f");
40
- const data = await emblemPost("/sign-typed-message", { vaultId, domain, types, message: value }, __classPrivateFieldGet(this, _EmblemEthersWallet_config, "f"));
53
+ if (!this._vaultId)
54
+ await this.initialize();
55
+ const cleanTypes = { ...types };
56
+ if (cleanTypes && cleanTypes.EIP712Domain) {
57
+ delete cleanTypes.EIP712Domain;
58
+ }
59
+ const data = await emblemPost("/sign-typed-message", { vaultId: this._vaultId, domain, types: cleanTypes, message: value }, this._config);
41
60
  return data.signature;
42
61
  }
62
+ async _signTypedData(domain, types, value) {
63
+ return this.signTypedData(domain, types, value);
64
+ }
43
65
  async signTransaction(tx) {
44
- // Ensure `from` (if present) matches this signer
66
+ if (!this._vaultId)
67
+ await this.initialize();
45
68
  const from = tx.from;
46
- if (from && from.toLowerCase() !== this.address.toLowerCase()) {
69
+ const addr = await this.getAddress();
70
+ if (from && from.toLowerCase() !== addr.toLowerCase()) {
47
71
  throw new Error("transaction from does not match signer address");
48
72
  }
49
- // Let provider fill fields if available
50
73
  const toSign = this.provider ? await this.populateTransaction(tx) : { ...tx };
51
- // Ethers serializers do not include `from`
52
- delete toSign.from;
74
+ if (toSign.from)
75
+ delete toSign.from;
76
+ if (!('to' in toSign) || !toSign.to) {
77
+ throw new Error("Transaction must have a 'to' address");
78
+ }
79
+ if (toSign.nonce === undefined || toSign.nonce === null) {
80
+ throw new Error("Transaction must have a nonce");
81
+ }
53
82
  const normalized = normalizeTxForEmblem(toSign);
54
- const vaultId = __classPrivateFieldGet(this, _EmblemEthersWallet_vaultId, "f");
55
- const resp = await emblemPost("/sign-eth-tx", { vaultId, transaction: normalized }, __classPrivateFieldGet(this, _EmblemEthersWallet_config, "f"));
83
+ const resp = await emblemPost("/sign-eth-tx", { vaultId: this._vaultId, transaction: normalized, options: { chainId: this._chainId } }, this._config);
56
84
  return resp.signedTransaction;
57
85
  }
58
86
  async sendTransaction(tx) {
59
- if (!this.provider) {
60
- throw new Error("EmblemEthersWallet requires a provider to send transactions");
61
- }
62
- const populated = await this.populateTransaction(tx);
63
- const signed = await this.signTransaction(populated);
87
+ if (!this.provider)
88
+ throw new Error("Provider required to send transaction");
89
+ const signed = await this.signTransaction(tx);
64
90
  return await this.provider.broadcastTransaction(signed);
65
91
  }
92
+ async populateTransaction(transaction) {
93
+ const tx = { ...transaction };
94
+ if (!this.provider)
95
+ throw new Error("Provider required to populate transaction");
96
+ const fromAddress = tx.from ? await resolveAddress(tx.from, this.provider) : await this.getAddress();
97
+ let chainId;
98
+ if (!tx.chainId) {
99
+ const network = await this.provider.getNetwork();
100
+ chainId = network.chainId;
101
+ this._chainId = Number(network.chainId);
102
+ }
103
+ else {
104
+ chainId = BigInt(tx.chainId);
105
+ this._chainId = Number(tx.chainId);
106
+ }
107
+ const nonce = tx.nonce != null ? Number(tx.nonce) : await this.provider.getTransactionCount(fromAddress, "pending");
108
+ const toAddress = tx.to ? await resolveAddress(tx.to, this.provider) : null;
109
+ const value = tx.value ? BigInt(tx.value.toString()) : 0n;
110
+ let gasLimit;
111
+ if (!tx.gasLimit) {
112
+ try {
113
+ gasLimit = await this.provider.estimateGas({ ...tx, from: fromAddress });
114
+ }
115
+ catch {
116
+ gasLimit = 21000n;
117
+ }
118
+ }
119
+ else {
120
+ gasLimit = BigInt(tx.gasLimit.toString());
121
+ }
122
+ let gasPrice = null;
123
+ if (!tx.gasPrice && tx.type !== 2) {
124
+ const feeData = await this.provider.getFeeData();
125
+ gasPrice = feeData.gasPrice ?? null;
126
+ }
127
+ else if (tx.gasPrice) {
128
+ gasPrice = BigInt(tx.gasPrice.toString());
129
+ }
130
+ const populated = {
131
+ from: fromAddress,
132
+ to: toAddress,
133
+ value,
134
+ nonce,
135
+ gasLimit,
136
+ data: tx.data,
137
+ chainId,
138
+ type: tx.type || undefined,
139
+ };
140
+ if (gasPrice !== null)
141
+ populated.gasPrice = gasPrice;
142
+ if (tx.maxFeePerGas)
143
+ populated.maxFeePerGas = BigInt(tx.maxFeePerGas.toString());
144
+ if (tx.maxPriorityFeePerGas)
145
+ populated.maxPriorityFeePerGas = BigInt(tx.maxPriorityFeePerGas.toString());
146
+ return populated;
147
+ }
148
+ async signAndBroadcast(transaction, waitForReceipt = false) {
149
+ if (!this.provider)
150
+ throw new Error("Provider required to send transaction");
151
+ const signed = await this.signTransaction(transaction);
152
+ const resp = await this.provider.broadcastTransaction(signed);
153
+ const hash = resp.hash;
154
+ if (waitForReceipt) {
155
+ await this.provider.waitForTransaction(hash);
156
+ }
157
+ return hash;
158
+ }
66
159
  }
67
- _EmblemEthersWallet_config = new WeakMap(), _EmblemEthersWallet_vaultId = new WeakMap();
68
160
  export async function toEthersWallet(config, provider, infoOverride) {
69
- const info = infoOverride ?? await fetchVaultInfo(config);
70
- return new EmblemEthersWallet(info.evmAddress, info.vaultId, config, provider ?? null);
161
+ const info = infoOverride ?? (await fetchVaultInfo(config));
162
+ return new EmblemEthersWallet(config, provider ?? null, { address: info.evmAddress, vaultId: info.vaultId });
71
163
  }
package/dist/types.d.ts CHANGED
@@ -8,6 +8,7 @@ export type EmblemRemoteConfig = {
8
8
  };
9
9
  export type VaultInfo = {
10
10
  vaultId: string;
11
+ tokenId?: string;
11
12
  address: string;
12
13
  evmAddress: `0x${string}`;
13
14
  created_by?: string;
package/dist/vault.js CHANGED
@@ -10,6 +10,7 @@ export async function fetchVaultInfo(config) {
10
10
  }
11
11
  return {
12
12
  vaultId: data.vaultId,
13
+ tokenId: data.vaultId,
13
14
  address: data.address,
14
15
  evmAddress: data.evmAddress,
15
16
  created_by: data.created_by,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emblem-vault-ai-signers",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Emblem Vault remote signer adapters for viem and ethers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,8 +9,10 @@
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
13
- }
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./package.json": "./package.json"
14
16
  },
15
17
  "files": [
16
18
  "dist"