@emblemvault/auth-sdk 2.0.2 → 2.1.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.
@@ -1,2 +1,2 @@
1
- "use strict";function t(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach(function(i){if("default"!==i){var r=Object.getOwnPropertyDescriptor(t,i);Object.defineProperty(e,i,r.get?r:{enumerable:!0,get:function(){return t[i]}})}}),e.default=t,Object.freeze(e)}async function e(t,e,i){const r=i.baseUrl??"https://api.emblemvault.ai",a=await async function(t){if("function"==typeof t.getAuthHeaders){const e=await t.getAuthHeaders();if(e&&"object"==typeof e)return e}const e=t.jwt??("function"==typeof t.getJwt?await t.getJwt():void 0)??t.sdk?.getSession()?.authToken??void 0;if(e)return{Authorization:`Bearer ${e}`};if(t.apiKey)return{"x-api-key":t.apiKey};throw new Error("No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey")}(i),n=await fetch(`${r}${t}`,{method:"POST",headers:{"content-type":"application/json",...a},body:JSON.stringify(e,(t,e)=>"bigint"==typeof e?e.toString():e)});if(!n.ok){const t=await n.text().catch(()=>"");throw new Error(function(t,e){let i=`Emblem signer error ${t}`;return t>=500?i+=": Internal server error":401===t||403===t?i+=": Authentication failed":404===t?i+=": Resource not found":405===t?i+=": Method not allowed":e&&(i+=`: ${e.substring(0,200)}`),i}(n.status,t))}return n.json()}function i(t,e){const i=Number(t);if(!Number.isSafeInteger(i))throw new Error(`${e} value ${t} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`);return i}function r(t){return"bigint"==typeof t?"0x"+t.toString(16):t}async function a(t){const i=await e("/vault/info",{},t);if(!i||!i.vaultId||!i.evmAddress)throw new Error("Invalid vault info response: missing required fields");if(!String(i.evmAddress).startsWith("0x"))throw new Error("Invalid evmAddress format in response");return{vaultId:i.vaultId,tokenId:i.vaultId,address:i.address||"",evmAddress:i.evmAddress,created_by:i.created_by}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.toEthersWallet=async function(n,s,o){let d;try{d=await Promise.resolve().then(function(){return t(require("ethers"))})}catch{throw new Error("ethers is required for toEthersWallet(). Install it with: npm install ethers")}const{AbstractSigner:c,resolveAddress:h}=d,u=o??await a(n);class l extends c{constructor(t,e,i){super(e??null),this._address=null,this._vaultId=null,this._chainId=1,this._config=t,i?.address&&(this._address=i.address),i?.vaultId&&(this._vaultId=i.vaultId),i?.chainId&&(this._chainId=i.chainId)}async initialize(){return this._initPromise||(this._initPromise=a(this._config).then(t=>{this._address=t.evmAddress,this._vaultId=t.vaultId}).catch(t=>{throw this._initPromise=void 0,t})),this._initPromise}async getAddress(){return this._address||await this.initialize(),this._address}getVaultId(){if(!this._vaultId)throw new Error("Wallet not initialized. Call initialize() first.");return this._vaultId}setChainId(t){this._chainId=t}getChainId(){return this._chainId}connect(t){if(!t)throw new Error("Provider cannot be null");return new l(this._config,t,{address:this._address??void 0,vaultId:this._vaultId??void 0,chainId:this._chainId})}async signMessage(t){this._vaultId||await this.initialize();const i="string"==typeof t?t:function(t){let e="0x";for(let i=0;i<t.length;i++)e+=t[i].toString(16).padStart(2,"0");return e}(t);return(await e("/sign-eth-message",{vaultId:this._vaultId,message:i},this._config)).signature}async signTypedData(t,i,r){this._vaultId||await this.initialize();const a={...i};a&&a.EIP712Domain&&delete a.EIP712Domain;return(await e("/sign-typed-message",{vaultId:this._vaultId,domain:t,types:a,message:r},this._config)).signature}async _signTypedData(t,e,i){return this.signTypedData(t,e,i)}async signTransaction(t){this._vaultId||await this.initialize();const a=t.from,n=await this.getAddress();if(a&&a.toLowerCase()!==n.toLowerCase())throw new Error("transaction from does not match signer address");const s=this.provider?{...await this.populateTransaction(t)}:{...t};if(s.from&&delete s.from,!("to"in s)||!s.to)throw new Error("Transaction must have a 'to' address");if(void 0===s.nonce||null===s.nonce)throw new Error("Transaction must have a nonce");const o=function(t){const e={...t};return void 0!==e.value&&(e.value=r(e.value)),void 0!==e.gas&&(e.gasLimit=r(e.gas),delete e.gas),void 0!==e.gasLimit&&(e.gasLimit=r(e.gasLimit)),void 0!==e.gasPrice&&(e.gasPrice=r(e.gasPrice)),void 0!==e.maxFeePerGas&&(e.maxFeePerGas=r(e.maxFeePerGas)),void 0!==e.maxPriorityFeePerGas&&(e.maxPriorityFeePerGas=r(e.maxPriorityFeePerGas)),void 0!==e.nonce&&(e.nonce=i(e.nonce,"nonce")),void 0!==e.chainId&&(e.chainId=i(e.chainId,"chainId")),void 0===e.maxFeePerGas&&void 0===e.maxPriorityFeePerGas||(void 0===e.gasPrice&&void 0!==e.maxFeePerGas&&(e.gasPrice=e.maxFeePerGas),delete e.maxFeePerGas,delete e.maxPriorityFeePerGas),delete e.type,delete e.accessList,delete e.account,delete e.chain,delete e.from,e}(s);return(await e("/sign-eth-tx",{vaultId:this._vaultId,transaction:o,options:{chainId:this._chainId}},this._config)).signedTransaction}async sendTransaction(t){if(!this.provider)throw new Error("Provider required to send transaction");const e=await this.signTransaction(t);return await this.provider.broadcastTransaction(e)}async populateTransaction(t){const e={...t};if(!this.provider)throw new Error("Provider required to populate transaction");const i=e.from?await h(e.from,this.provider):await this.getAddress();let r;if(e.chainId)r=BigInt(e.chainId),this._chainId=Number(e.chainId);else{const t=await this.provider.getNetwork();r=t.chainId,this._chainId=Number(t.chainId)}const a=null!=e.nonce?Number(e.nonce):await this.provider.getTransactionCount(i,"pending"),n=e.to?await h(e.to,this.provider):null,s=e.value?BigInt(e.value.toString()):0n;let o;if(e.gasLimit)o=BigInt(e.gasLimit.toString());else try{o=await this.provider.estimateGas({...e,from:i})}catch{o=21000n}let d=null;if(e.gasPrice||2===e.type)e.gasPrice&&(d=BigInt(e.gasPrice.toString()));else{d=(await this.provider.getFeeData()).gasPrice??null}const c={from:i,to:n,value:s,nonce:a,gasLimit:o,data:e.data,chainId:r,type:e.type||void 0};return null!==d&&(c.gasPrice=d),e.maxFeePerGas&&(c.maxFeePerGas=BigInt(e.maxFeePerGas.toString())),e.maxPriorityFeePerGas&&(c.maxPriorityFeePerGas=BigInt(e.maxPriorityFeePerGas.toString())),c}async signAndBroadcast(t,e=!1){if(!this.provider)throw new Error("Provider required to send transaction");const i=await this.signTransaction(t),r=(await this.provider.broadcastTransaction(i)).hash;return e&&await this.provider.waitForTransaction(r),r}}return new l(n,s,{address:u.evmAddress,vaultId:u.vaultId})};
1
+ "use strict";function t(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach(function(i){if("default"!==i){var r=Object.getOwnPropertyDescriptor(t,i);Object.defineProperty(e,i,r.get?r:{enumerable:!0,get:function(){return t[i]}})}}),e.default=t,Object.freeze(e)}async function e(t,e,i){const r=i.baseUrl??"https://api.emblemvault.ai",a=await async function(t){if("function"==typeof t.getAuthHeaders){const e=await t.getAuthHeaders();if(e&&"object"==typeof e)return e}const e=t.jwt??("function"==typeof t.getJwt?await t.getJwt():void 0)??t.sdk?.getSession()?.authToken??void 0;if(e)return{Authorization:`Bearer ${e}`};if(t.apiKey)return{"x-api-key":t.apiKey};throw new Error("No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey")}(i),n=await fetch(`${r}${t}`,{method:"POST",headers:{"content-type":"application/json",...a},body:JSON.stringify(e,(t,e)=>"bigint"==typeof e?e.toString():e)});if(!n.ok){const t=await n.text().catch(()=>"");throw new Error(function(t,e){let i=`Emblem signer error ${t}`;return t>=500?i+=": Internal server error":401===t||403===t?i+=": Authentication failed":404===t?i+=": Resource not found":405===t?i+=": Method not allowed":e&&(i+=`: ${e.substring(0,200)}`),i}(n.status,t))}return n.json()}function i(t,e){const i=Number(t);if(!Number.isSafeInteger(i))throw new Error(`${e} value ${t} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`);return i}function r(t){return"bigint"==typeof t?"0x"+t.toString(16):t}async function a(t){const i=await e("/vault/info",{},t);if(!i||!i.vaultId||!i.evmAddress)throw new Error("Invalid vault info response: missing required fields");if(!String(i.evmAddress).startsWith("0x"))throw new Error("Invalid evmAddress format in response");return{vaultId:i.vaultId,tokenId:i.vaultId,address:i.address||"",evmAddress:i.evmAddress,created_by:i.created_by}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.toEthersWallet=async function(n,s,o){let d;try{const e="ethers";d=await(c=e,Promise.resolve().then(function(){return t(require(c))}))}catch{throw new Error("ethers is required for toEthersWallet(). Install it with: npm install ethers")}var c;const{AbstractSigner:h,resolveAddress:u}=d,l=o??await a(n);class g extends h{constructor(t,e,i){super(e??null),this._address=null,this._vaultId=null,this._chainId=1,this._config=t,i?.address&&(this._address=i.address),i?.vaultId&&(this._vaultId=i.vaultId),i?.chainId&&(this._chainId=i.chainId)}async initialize(){return this._initPromise||(this._initPromise=a(this._config).then(t=>{this._address=t.evmAddress,this._vaultId=t.vaultId}).catch(t=>{throw this._initPromise=void 0,t})),this._initPromise}async getAddress(){return this._address||await this.initialize(),this._address}getVaultId(){if(!this._vaultId)throw new Error("Wallet not initialized. Call initialize() first.");return this._vaultId}setChainId(t){this._chainId=t}getChainId(){return this._chainId}connect(t){if(!t)throw new Error("Provider cannot be null");return new g(this._config,t,{address:this._address??void 0,vaultId:this._vaultId??void 0,chainId:this._chainId})}async signMessage(t){this._vaultId||await this.initialize();const i="string"==typeof t?t:function(t){let e="0x";for(let i=0;i<t.length;i++)e+=t[i].toString(16).padStart(2,"0");return e}(t);return(await e("/sign-eth-message",{vaultId:this._vaultId,message:i},this._config)).signature}async signTypedData(t,i,r){this._vaultId||await this.initialize();const a={...i};a&&a.EIP712Domain&&delete a.EIP712Domain;return(await e("/sign-typed-message",{vaultId:this._vaultId,domain:t,types:a,message:r},this._config)).signature}async _signTypedData(t,e,i){return this.signTypedData(t,e,i)}async signTransaction(t){this._vaultId||await this.initialize();const a=t.from,n=await this.getAddress();if(a&&a.toLowerCase()!==n.toLowerCase())throw new Error("transaction from does not match signer address");const s=this.provider?{...await this.populateTransaction(t)}:{...t};if(s.from&&delete s.from,!("to"in s)||!s.to)throw new Error("Transaction must have a 'to' address");if(void 0===s.nonce||null===s.nonce)throw new Error("Transaction must have a nonce");const o=function(t){const e={...t};return void 0!==e.value&&(e.value=r(e.value)),void 0!==e.gas&&(e.gasLimit=r(e.gas),delete e.gas),void 0!==e.gasLimit&&(e.gasLimit=r(e.gasLimit)),void 0!==e.gasPrice&&(e.gasPrice=r(e.gasPrice)),void 0!==e.maxFeePerGas&&(e.maxFeePerGas=r(e.maxFeePerGas)),void 0!==e.maxPriorityFeePerGas&&(e.maxPriorityFeePerGas=r(e.maxPriorityFeePerGas)),void 0!==e.nonce&&(e.nonce=i(e.nonce,"nonce")),void 0!==e.chainId&&(e.chainId=i(e.chainId,"chainId")),void 0===e.maxFeePerGas&&void 0===e.maxPriorityFeePerGas||(void 0===e.gasPrice&&void 0!==e.maxFeePerGas&&(e.gasPrice=e.maxFeePerGas),delete e.maxFeePerGas,delete e.maxPriorityFeePerGas),delete e.type,delete e.accessList,delete e.account,delete e.chain,delete e.from,e}(s);return(await e("/sign-eth-tx",{vaultId:this._vaultId,transaction:o,options:{chainId:this._chainId}},this._config)).signedTransaction}async sendTransaction(t){if(!this.provider)throw new Error("Provider required to send transaction");const e=await this.signTransaction(t);return await this.provider.broadcastTransaction(e)}async populateTransaction(t){const e={...t};if(!this.provider)throw new Error("Provider required to populate transaction");const i=e.from?await u(e.from,this.provider):await this.getAddress();let r;if(e.chainId)r=BigInt(e.chainId),this._chainId=Number(e.chainId);else{const t=await this.provider.getNetwork();r=t.chainId,this._chainId=Number(t.chainId)}const a=null!=e.nonce?Number(e.nonce):await this.provider.getTransactionCount(i,"pending"),n=e.to?await u(e.to,this.provider):null,s=e.value?BigInt(e.value.toString()):0n;let o;if(e.gasLimit)o=BigInt(e.gasLimit.toString());else try{o=await this.provider.estimateGas({...e,from:i})}catch{o=21000n}let d=null;if(e.gasPrice||2===e.type)e.gasPrice&&(d=BigInt(e.gasPrice.toString()));else{d=(await this.provider.getFeeData()).gasPrice??null}const c={from:i,to:n,value:s,nonce:a,gasLimit:o,data:e.data,chainId:r,type:e.type||void 0};return null!==d&&(c.gasPrice=d),e.maxFeePerGas&&(c.maxFeePerGas=BigInt(e.maxFeePerGas.toString())),e.maxPriorityFeePerGas&&(c.maxPriorityFeePerGas=BigInt(e.maxPriorityFeePerGas.toString())),c}async signAndBroadcast(t,e=!1){if(!this.provider)throw new Error("Provider required to send transaction");const i=await this.signTransaction(t),r=(await this.provider.broadcastTransaction(i)).hash;return e&&await this.provider.waitForTransaction(r),r}}return new g(n,s,{address:l.evmAddress,vaultId:l.vaultId})};
2
2
  //# sourceMappingURL=ethers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ethers.js","sources":["../../src/signers/http.ts","../../src/signers/validation.ts","../../src/signers/utils.ts","../../src/signers/vault.ts","../../src/signers/ethers.ts"],"sourcesContent":["import type { SignerConfig } from '../types/signers';\n\nfunction sanitizeErrorMessage(status: number, text: string): string {\n // Sanitize error messages to avoid leaking sensitive server information\n let errorMessage = `Emblem signer error ${status}`;\n\n if (status >= 500) {\n errorMessage += ': Internal server error';\n } else if (status === 401 || status === 403) {\n errorMessage += ': Authentication failed';\n } else if (status === 404) {\n errorMessage += ': Resource not found';\n } else if (status === 405) {\n errorMessage += ': Method not allowed';\n } else if (text) {\n // For 4xx client errors, include limited error details\n errorMessage += `: ${text.substring(0, 200)}`; // Limit to 200 chars\n }\n\n return errorMessage;\n}\n\nasync function resolveAuthHeaders(config: SignerConfig): Promise<Record<string, string>> {\n // Priority: custom headers -> jwt/getJwt/sdk -> apiKey (deprecated)\n if (typeof config.getAuthHeaders === 'function') {\n const h = await config.getAuthHeaders();\n if (h && typeof h === 'object') return h;\n }\n\n const tok =\n config.jwt ??\n (typeof config.getJwt === 'function' ? await config.getJwt() : undefined) ??\n config.sdk?.getSession()?.authToken ??\n undefined;\n\n if (tok) {\n return { Authorization: `Bearer ${tok}` };\n }\n\n // apiKey is deprecated but still supported as fallback\n if (config.apiKey) {\n return { 'x-api-key': config.apiKey };\n }\n\n throw new Error(\n 'No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey'\n );\n}\n\nexport async function emblemPost<T = unknown>(\n path: string,\n body: unknown,\n config: SignerConfig\n): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n ...authHeaders,\n },\n body: JSON.stringify(body, (_key: string, value: unknown) =>\n typeof value === 'bigint' ? value.toString() : value\n ),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n\nexport async function emblemGet<T = unknown>(path: string, config: SignerConfig): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'GET',\n headers: authHeaders,\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n","import type { SignerConfig } from '../types/signers';\n\n/**\n * Environment detection utilities for warning about unsafe usage patterns\n */\n\n/**\n * Detect if code is running in a browser environment\n */\nexport function isBrowserEnvironment(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if we're in a Node.js server environment\n */\nexport function isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' && process.versions != null && process.versions.node != null\n );\n}\n\n/**\n * Validate baseUrl format\n */\nexport function validateBaseUrl(baseUrl?: string): void {\n if (!baseUrl) return; // undefined is ok, will use default\n\n if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {\n throw new Error('baseUrl must be a valid HTTP(S) URL');\n }\n\n // Warn about http (not https)\n if (\n baseUrl.startsWith('http://') &&\n !baseUrl.includes('localhost') &&\n !baseUrl.includes('127.0.0.1')\n ) {\n console.warn(\n '[Emblem Security Warning] baseUrl uses HTTP instead of HTTPS. This is insecure for production use.'\n );\n }\n}\n\n/**\n * Validate Ethereum address format\n */\nexport function validateEthereumAddress(address: string): void {\n if (!address || typeof address !== 'string') {\n throw new Error('Address is required');\n }\n\n if (!address.startsWith('0x')) {\n throw new Error('Address must start with 0x');\n }\n\n if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {\n throw new Error('Invalid Ethereum address format');\n }\n}\n\n/**\n * Validate vault ID\n */\nexport function validateVaultId(vaultId: string): void {\n if (!vaultId || typeof vaultId !== 'string') {\n throw new Error('vaultId is required');\n }\n\n if (vaultId.trim() === '') {\n throw new Error('vaultId cannot be empty');\n }\n}\n\n/**\n * Safe number conversion with bounds checking\n */\nexport function toSafeNumber(value: unknown, fieldName: string): number {\n const num = Number(value);\n\n if (!Number.isSafeInteger(num)) {\n throw new Error(\n `${fieldName} value ${value} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`\n );\n }\n\n return num;\n}\n\n/**\n * Extended config with security options\n */\nexport interface SignerSecurityConfig extends SignerConfig {\n /**\n * Enable debug logging for security-related checks\n * @default false\n */\n debugSecurity?: boolean;\n}\n\n/**\n * Validate signer configuration\n */\nexport function validateSignerConfig(config: SignerSecurityConfig): void {\n // Validate auth: require at least one method (jwt, getJwt, getAuthHeaders)\n const hasJwt = !!config.jwt;\n const hasGetJwt = typeof config.getJwt === 'function';\n const hasHeaders = typeof config.getAuthHeaders === 'function';\n\n if (!hasJwt && !hasGetJwt && !hasHeaders) {\n throw new Error('Authentication required: provide jwt, getJwt(), or getAuthHeaders()');\n }\n\n // Validate baseUrl if provided\n if (config.baseUrl) {\n validateBaseUrl(config.baseUrl);\n }\n\n // Security audit logging\n if (config.debugSecurity) {\n console.log('[Emblem Security Debug]', {\n environment: isBrowserEnvironment() ? 'browser' : 'node',\n hasBaseUrl: !!config.baseUrl,\n timestamp: new Date().toISOString(),\n });\n }\n}\n","import type { Hex } from '../types/signers';\nimport { toSafeNumber } from './validation';\n\nexport function toHexIfBigInt(v: unknown): unknown {\n return typeof v === 'bigint' ? '0x' + v.toString(16) : v;\n}\n\n/**\n * viem txs sometimes have bigint / hex / optional fields. Ethers serializers\n * accept hex strings for numeric fields. Normalize where helpful.\n */\nexport function normalizeTxForEmblem(tx: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...tx };\n\n if (out.value !== undefined) out.value = toHexIfBigInt(out.value);\n if (out.gas !== undefined) {\n out.gasLimit = toHexIfBigInt(out.gas);\n delete out.gas;\n }\n if (out.gasLimit !== undefined) out.gasLimit = toHexIfBigInt(out.gasLimit);\n if (out.gasPrice !== undefined) out.gasPrice = toHexIfBigInt(out.gasPrice);\n if (out.maxFeePerGas !== undefined) out.maxFeePerGas = toHexIfBigInt(out.maxFeePerGas);\n if (out.maxPriorityFeePerGas !== undefined)\n out.maxPriorityFeePerGas = toHexIfBigInt(out.maxPriorityFeePerGas);\n if (out.nonce !== undefined) out.nonce = toSafeNumber(out.nonce, 'nonce');\n if (out.chainId !== undefined) out.chainId = toSafeNumber(out.chainId, 'chainId');\n\n // Some backends only accept legacy fields; fold EIP-1559 into gasPrice and drop unsupported keys\n if (out.maxFeePerGas !== undefined || out.maxPriorityFeePerGas !== undefined) {\n if (out.gasPrice === undefined && out.maxFeePerGas !== undefined) {\n out.gasPrice = out.maxFeePerGas;\n }\n delete out.maxFeePerGas;\n delete out.maxPriorityFeePerGas;\n }\n\n // Remove fields commonly unsupported by legacy serializers\n delete out.type;\n delete out.accessList;\n delete out.account;\n delete out.chain;\n delete out.from;\n\n return out;\n}\n\nexport function isHexString(value: unknown): value is Hex {\n return typeof value === 'string' && /^0x[0-9a-fA-F]*$/.test(value);\n}\n\nexport function bytesToHex(bytes: ArrayLike<number>): Hex {\n let out = '0x';\n for (let i = 0; i < bytes.length; i++) {\n out += (bytes[i] as number).toString(16).padStart(2, '0');\n }\n return out as Hex;\n}\n","import type { SignerConfig, SignerVaultInfo, Hex } from '../types/signers';\nimport { emblemPost } from './http';\n\nexport async function fetchVaultInfo(config: SignerConfig): Promise<SignerVaultInfo> {\n // Note: The server only supports POST for /vault/info\n const data: Partial<{\n vaultId: string;\n address: string;\n evmAddress: Hex;\n created_by?: string;\n }> = await emblemPost('/vault/info', {}, config);\n\n // Validate required response data (vaultId + evmAddress are required for EVM)\n if (!data || !data.vaultId || !data.evmAddress) {\n throw new Error('Invalid vault info response: missing required fields');\n }\n\n if (!String(data.evmAddress).startsWith('0x')) {\n throw new Error('Invalid evmAddress format in response');\n }\n\n return {\n vaultId: data.vaultId,\n tokenId: data.vaultId,\n address: data.address || '', // Solana address may be absent; keep optional\n evmAddress: data.evmAddress as Hex,\n created_by: data.created_by,\n };\n}\n","import type { Hex, SignerConfig, SignerVaultInfo } from '../types/signers';\nimport { emblemPost } from './http';\nimport { bytesToHex, normalizeTxForEmblem } from './utils';\nimport { fetchVaultInfo } from './vault';\n\n// ethers v6 compatible interface (like solana pattern - no runtime dependency)\nexport interface EmblemEthersWallet {\n getAddress(): Promise<string>;\n signMessage(message: string | Uint8Array): Promise<string>;\n signTypedData(\n domain: unknown,\n types: Record<string, Array<{ name: string; type: string }>>,\n value: Record<string, unknown>\n ): Promise<string>;\n signTransaction(tx: unknown): Promise<string>;\n sendTransaction(tx: unknown): Promise<unknown>;\n connect(provider: unknown): EmblemEthersWallet;\n provider: unknown;\n // Additional methods\n initialize(): Promise<void>;\n getVaultId(): string;\n setChainId(chainId: number): void;\n getChainId(): number;\n signAndBroadcast(transaction: unknown, waitForReceipt?: boolean): Promise<string>;\n}\n\nexport async function toEthersWallet(\n config: SignerConfig,\n provider?: unknown | null,\n infoOverride?: SignerVaultInfo\n): Promise<EmblemEthersWallet> {\n // Dynamic import - only loads ethers when this function is called\n // webpackIgnore comment prevents webpack from trying to resolve at build time\n let ethers: typeof import('ethers');\n try {\n ethers = await import(/* webpackIgnore: true */ 'ethers');\n } catch {\n throw new Error('ethers is required for toEthersWallet(). Install it with: npm install ethers');\n }\n\n const { AbstractSigner, resolveAddress } = ethers;\n type AbstractProvider = import('ethers').AbstractProvider;\n type TransactionRequest = import('ethers').TransactionRequest;\n type TransactionResponse = import('ethers').TransactionResponse;\n type TransactionLike = import('ethers').TransactionLike<string>;\n type TypedDataDomain = import('ethers').TypedDataDomain;\n type TypedDataField = import('ethers').TypedDataField;\n\n const info = infoOverride ?? (await fetchVaultInfo(config));\n\n // Class defined inside function after dynamic import\n class EmblemEthersWalletImpl extends AbstractSigner {\n private readonly _config: SignerConfig;\n private _address: Hex | null = null;\n private _vaultId: string | null = null;\n private _chainId = 1;\n private _initPromise?: Promise<void>;\n\n constructor(\n signerConfig: SignerConfig,\n signerProvider?: AbstractProvider | null,\n seed?: { address?: Hex; vaultId?: string; chainId?: number }\n ) {\n super(signerProvider ?? null);\n this._config = signerConfig;\n if (seed?.address) this._address = seed.address;\n if (seed?.vaultId) this._vaultId = seed.vaultId;\n if (seed?.chainId) this._chainId = seed.chainId;\n }\n\n async initialize(): Promise<void> {\n if (this._initPromise) return this._initPromise;\n\n this._initPromise = fetchVaultInfo(this._config)\n .then((vaultInfo) => {\n this._address = vaultInfo.evmAddress;\n this._vaultId = vaultInfo.vaultId;\n })\n .catch((err) => {\n this._initPromise = undefined;\n throw err;\n });\n\n return this._initPromise;\n }\n\n async getAddress(): Promise<string> {\n if (!this._address) await this.initialize();\n return this._address!;\n }\n\n getVaultId(): string {\n if (!this._vaultId) throw new Error('Wallet not initialized. Call initialize() first.');\n return this._vaultId;\n }\n\n setChainId(chainId: number): void {\n this._chainId = chainId;\n }\n\n getChainId(): number {\n return this._chainId;\n }\n\n connect(newProvider: AbstractProvider): EmblemEthersWalletImpl {\n if (!newProvider) throw new Error('Provider cannot be null');\n return new EmblemEthersWalletImpl(this._config, newProvider, {\n address: this._address ?? undefined,\n vaultId: this._vaultId ?? undefined,\n chainId: this._chainId,\n });\n }\n\n async signMessage(message: string | Uint8Array): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const payload = typeof message === 'string' ? message : bytesToHex(message);\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-eth-message',\n { vaultId: this._vaultId!, message: payload },\n this._config\n );\n return data.signature;\n }\n\n async signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const cleanTypes = { ...types };\n if (cleanTypes && (cleanTypes as Record<string, unknown>).EIP712Domain) {\n delete (cleanTypes as Record<string, unknown>).EIP712Domain;\n }\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-typed-message',\n { vaultId: this._vaultId!, domain, types: cleanTypes, message: value },\n this._config\n );\n return data.signature;\n }\n\n async _signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n return this.signTypedData(domain, types, value);\n }\n\n async signTransaction(tx: TransactionRequest): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const from = (tx as Record<string, unknown>).from as string | undefined;\n const addr = await this.getAddress();\n\n if (from && from.toLowerCase() !== addr.toLowerCase()) {\n throw new Error('transaction from does not match signer address');\n }\n\n const toSign = this.provider\n ? ({ ...await this.populateTransaction(tx) } as Record<string, unknown>)\n : ({ ...tx } as Record<string, unknown>);\n if (toSign.from) delete toSign.from;\n if (!('to' in toSign) || !toSign.to) {\n throw new Error(\"Transaction must have a 'to' address\");\n }\n if (toSign.nonce === undefined || toSign.nonce === null) {\n throw new Error('Transaction must have a nonce');\n }\n const normalized = normalizeTxForEmblem(toSign);\n const resp = await emblemPost<{ signedTransaction: Hex }>(\n '/sign-eth-tx',\n { vaultId: this._vaultId!, transaction: normalized, options: { chainId: this._chainId } },\n this._config\n );\n return resp.signedTransaction;\n }\n\n async sendTransaction(tx: TransactionRequest): Promise<TransactionResponse> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(tx);\n return await this.provider.broadcastTransaction(signed);\n }\n\n async populateTransaction(transaction: TransactionRequest): Promise<TransactionLike> {\n const tx = { ...transaction } as TransactionRequest;\n if (!this.provider) throw new Error('Provider required to populate transaction');\n const fromAddress = tx.from\n ? await resolveAddress(tx.from, this.provider)\n : await this.getAddress();\n\n let chainId: bigint;\n if (!tx.chainId) {\n const network = await this.provider.getNetwork();\n chainId = network.chainId;\n this._chainId = Number(network.chainId);\n } else {\n chainId = BigInt(tx.chainId);\n this._chainId = Number(tx.chainId);\n }\n\n const nonce =\n tx.nonce != null\n ? Number(tx.nonce)\n : await this.provider.getTransactionCount(fromAddress, 'pending');\n const toAddress = tx.to ? await resolveAddress(tx.to, this.provider) : null;\n const value = tx.value ? BigInt(tx.value.toString()) : 0n;\n\n let gasLimit: bigint;\n if (!tx.gasLimit) {\n try {\n gasLimit = await this.provider.estimateGas({ ...tx, from: fromAddress });\n } catch {\n gasLimit = 21000n;\n }\n } else {\n gasLimit = BigInt(tx.gasLimit.toString());\n }\n\n let gasPrice: bigint | null = null;\n if (!tx.gasPrice && tx.type !== 2) {\n const feeData = await this.provider.getFeeData();\n gasPrice = feeData.gasPrice ?? null;\n } else if (tx.gasPrice) {\n gasPrice = BigInt(tx.gasPrice.toString());\n }\n\n const populated: TransactionLike = {\n from: fromAddress,\n to: toAddress,\n value,\n nonce,\n gasLimit,\n data: tx.data as string | undefined,\n chainId,\n type: tx.type || undefined,\n };\n if (gasPrice !== null) populated.gasPrice = gasPrice;\n if (tx.maxFeePerGas) populated.maxFeePerGas = BigInt(tx.maxFeePerGas.toString());\n if (tx.maxPriorityFeePerGas)\n populated.maxPriorityFeePerGas = BigInt(tx.maxPriorityFeePerGas.toString());\n return populated;\n }\n\n async signAndBroadcast(\n transaction: TransactionRequest,\n waitForReceipt: boolean = false\n ): Promise<string> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(transaction);\n const resp = await this.provider.broadcastTransaction(signed);\n const hash = resp.hash as string;\n if (waitForReceipt) {\n await this.provider.waitForTransaction(hash);\n }\n return hash;\n }\n }\n\n return new EmblemEthersWalletImpl(config, provider as AbstractProvider | null, {\n address: info.evmAddress,\n vaultId: info.vaultId,\n });\n}\n"],"names":["async","emblemPost","path","body","config","baseUrl","authHeaders","getAuthHeaders","h","tok","jwt","getJwt","undefined","sdk","getSession","authToken","Authorization","apiKey","Error","resolveAuthHeaders","res","fetch","method","headers","JSON","stringify","_key","value","toString","ok","text","catch","status","errorMessage","substring","sanitizeErrorMessage","json","toSafeNumber","fieldName","num","Number","isSafeInteger","MAX_SAFE_INTEGER","toHexIfBigInt","v","fetchVaultInfo","data","vaultId","evmAddress","String","startsWith","tokenId","address","created_by","provider","infoOverride","ethers","Promise","AbstractSigner","resolveAddress","info","EmblemEthersWalletImpl","constructor","signerConfig","signerProvider","seed","super","this","_address","_vaultId","_chainId","_config","chainId","initialize","_initPromise","then","vaultInfo","err","getAddress","getVaultId","setChainId","getChainId","connect","newProvider","signMessage","message","payload","bytes","out","i","length","padStart","bytesToHex","signature","signTypedData","domain","types","cleanTypes","EIP712Domain","_signTypedData","signTransaction","tx","from","addr","toLowerCase","toSign","populateTransaction","to","nonce","normalized","gas","gasLimit","gasPrice","maxFeePerGas","maxPriorityFeePerGas","type","accessList","account","chain","normalizeTxForEmblem","transaction","options","signedTransaction","sendTransaction","signed","broadcastTransaction","fromAddress","BigInt","network","getNetwork","getTransactionCount","toAddress","estimateGas","getFeeData","populated","signAndBroadcast","waitForReceipt","hash","waitForTransaction"],"mappings":"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"}
1
+ {"version":3,"file":"ethers.js","sources":["../../src/signers/http.ts","../../src/signers/validation.ts","../../src/signers/utils.ts","../../src/signers/vault.ts","../../src/signers/ethers.ts"],"sourcesContent":["import type { SignerConfig } from '../types/signers';\n\nfunction sanitizeErrorMessage(status: number, text: string): string {\n // Sanitize error messages to avoid leaking sensitive server information\n let errorMessage = `Emblem signer error ${status}`;\n\n if (status >= 500) {\n errorMessage += ': Internal server error';\n } else if (status === 401 || status === 403) {\n errorMessage += ': Authentication failed';\n } else if (status === 404) {\n errorMessage += ': Resource not found';\n } else if (status === 405) {\n errorMessage += ': Method not allowed';\n } else if (text) {\n // For 4xx client errors, include limited error details\n errorMessage += `: ${text.substring(0, 200)}`; // Limit to 200 chars\n }\n\n return errorMessage;\n}\n\nasync function resolveAuthHeaders(config: SignerConfig): Promise<Record<string, string>> {\n // Priority: custom headers -> jwt/getJwt/sdk -> apiKey (deprecated)\n if (typeof config.getAuthHeaders === 'function') {\n const h = await config.getAuthHeaders();\n if (h && typeof h === 'object') return h;\n }\n\n const tok =\n config.jwt ??\n (typeof config.getJwt === 'function' ? await config.getJwt() : undefined) ??\n config.sdk?.getSession()?.authToken ??\n undefined;\n\n if (tok) {\n return { Authorization: `Bearer ${tok}` };\n }\n\n // apiKey is deprecated but still supported as fallback\n if (config.apiKey) {\n return { 'x-api-key': config.apiKey };\n }\n\n throw new Error(\n 'No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey'\n );\n}\n\nexport async function emblemPost<T = unknown>(\n path: string,\n body: unknown,\n config: SignerConfig\n): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n ...authHeaders,\n },\n body: JSON.stringify(body, (_key: string, value: unknown) =>\n typeof value === 'bigint' ? value.toString() : value\n ),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n\nexport async function emblemGet<T = unknown>(path: string, config: SignerConfig): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'GET',\n headers: authHeaders,\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n","import type { SignerConfig } from '../types/signers';\n\n/**\n * Environment detection utilities for warning about unsafe usage patterns\n */\n\n/**\n * Detect if code is running in a browser environment\n */\nexport function isBrowserEnvironment(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if we're in a Node.js server environment\n */\nexport function isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' && process.versions != null && process.versions.node != null\n );\n}\n\n/**\n * Validate baseUrl format\n */\nexport function validateBaseUrl(baseUrl?: string): void {\n if (!baseUrl) return; // undefined is ok, will use default\n\n if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {\n throw new Error('baseUrl must be a valid HTTP(S) URL');\n }\n\n // Warn about http (not https)\n if (\n baseUrl.startsWith('http://') &&\n !baseUrl.includes('localhost') &&\n !baseUrl.includes('127.0.0.1')\n ) {\n console.warn(\n '[Emblem Security Warning] baseUrl uses HTTP instead of HTTPS. This is insecure for production use.'\n );\n }\n}\n\n/**\n * Validate Ethereum address format\n */\nexport function validateEthereumAddress(address: string): void {\n if (!address || typeof address !== 'string') {\n throw new Error('Address is required');\n }\n\n if (!address.startsWith('0x')) {\n throw new Error('Address must start with 0x');\n }\n\n if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {\n throw new Error('Invalid Ethereum address format');\n }\n}\n\n/**\n * Validate vault ID\n */\nexport function validateVaultId(vaultId: string): void {\n if (!vaultId || typeof vaultId !== 'string') {\n throw new Error('vaultId is required');\n }\n\n if (vaultId.trim() === '') {\n throw new Error('vaultId cannot be empty');\n }\n}\n\n/**\n * Safe number conversion with bounds checking\n */\nexport function toSafeNumber(value: unknown, fieldName: string): number {\n const num = Number(value);\n\n if (!Number.isSafeInteger(num)) {\n throw new Error(\n `${fieldName} value ${value} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`\n );\n }\n\n return num;\n}\n\n/**\n * Extended config with security options\n */\nexport interface SignerSecurityConfig extends SignerConfig {\n /**\n * Enable debug logging for security-related checks\n * @default false\n */\n debugSecurity?: boolean;\n}\n\n/**\n * Validate signer configuration\n */\nexport function validateSignerConfig(config: SignerSecurityConfig): void {\n // Validate auth: require at least one method (jwt, getJwt, getAuthHeaders)\n const hasJwt = !!config.jwt;\n const hasGetJwt = typeof config.getJwt === 'function';\n const hasHeaders = typeof config.getAuthHeaders === 'function';\n\n if (!hasJwt && !hasGetJwt && !hasHeaders) {\n throw new Error('Authentication required: provide jwt, getJwt(), or getAuthHeaders()');\n }\n\n // Validate baseUrl if provided\n if (config.baseUrl) {\n validateBaseUrl(config.baseUrl);\n }\n\n // Security audit logging\n if (config.debugSecurity) {\n console.log('[Emblem Security Debug]', {\n environment: isBrowserEnvironment() ? 'browser' : 'node',\n hasBaseUrl: !!config.baseUrl,\n timestamp: new Date().toISOString(),\n });\n }\n}\n","import type { Hex } from '../types/signers';\nimport { toSafeNumber } from './validation';\n\nexport function toHexIfBigInt(v: unknown): unknown {\n return typeof v === 'bigint' ? '0x' + v.toString(16) : v;\n}\n\n/**\n * viem txs sometimes have bigint / hex / optional fields. Ethers serializers\n * accept hex strings for numeric fields. Normalize where helpful.\n */\nexport function normalizeTxForEmblem(tx: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...tx };\n\n if (out.value !== undefined) out.value = toHexIfBigInt(out.value);\n if (out.gas !== undefined) {\n out.gasLimit = toHexIfBigInt(out.gas);\n delete out.gas;\n }\n if (out.gasLimit !== undefined) out.gasLimit = toHexIfBigInt(out.gasLimit);\n if (out.gasPrice !== undefined) out.gasPrice = toHexIfBigInt(out.gasPrice);\n if (out.maxFeePerGas !== undefined) out.maxFeePerGas = toHexIfBigInt(out.maxFeePerGas);\n if (out.maxPriorityFeePerGas !== undefined)\n out.maxPriorityFeePerGas = toHexIfBigInt(out.maxPriorityFeePerGas);\n if (out.nonce !== undefined) out.nonce = toSafeNumber(out.nonce, 'nonce');\n if (out.chainId !== undefined) out.chainId = toSafeNumber(out.chainId, 'chainId');\n\n // Some backends only accept legacy fields; fold EIP-1559 into gasPrice and drop unsupported keys\n if (out.maxFeePerGas !== undefined || out.maxPriorityFeePerGas !== undefined) {\n if (out.gasPrice === undefined && out.maxFeePerGas !== undefined) {\n out.gasPrice = out.maxFeePerGas;\n }\n delete out.maxFeePerGas;\n delete out.maxPriorityFeePerGas;\n }\n\n // Remove fields commonly unsupported by legacy serializers\n delete out.type;\n delete out.accessList;\n delete out.account;\n delete out.chain;\n delete out.from;\n\n return out;\n}\n\nexport function isHexString(value: unknown): value is Hex {\n return typeof value === 'string' && /^0x[0-9a-fA-F]*$/.test(value);\n}\n\nexport function bytesToHex(bytes: ArrayLike<number>): Hex {\n let out = '0x';\n for (let i = 0; i < bytes.length; i++) {\n out += (bytes[i] as number).toString(16).padStart(2, '0');\n }\n return out as Hex;\n}\n","import type { SignerConfig, SignerVaultInfo, Hex } from '../types/signers';\nimport { emblemPost } from './http';\n\nexport async function fetchVaultInfo(config: SignerConfig): Promise<SignerVaultInfo> {\n // Note: The server only supports POST for /vault/info\n const data: Partial<{\n vaultId: string;\n address: string;\n evmAddress: Hex;\n created_by?: string;\n }> = await emblemPost('/vault/info', {}, config);\n\n // Validate required response data (vaultId + evmAddress are required for EVM)\n if (!data || !data.vaultId || !data.evmAddress) {\n throw new Error('Invalid vault info response: missing required fields');\n }\n\n if (!String(data.evmAddress).startsWith('0x')) {\n throw new Error('Invalid evmAddress format in response');\n }\n\n return {\n vaultId: data.vaultId,\n tokenId: data.vaultId,\n address: data.address || '', // Solana address may be absent; keep optional\n evmAddress: data.evmAddress as Hex,\n created_by: data.created_by,\n };\n}\n","import type { Hex, SignerConfig, SignerVaultInfo } from '../types/signers';\nimport { emblemPost } from './http';\nimport { bytesToHex, normalizeTxForEmblem } from './utils';\nimport { fetchVaultInfo } from './vault';\n\n// ethers v6 compatible interface (like solana pattern - no runtime dependency)\nexport interface EmblemEthersWallet {\n getAddress(): Promise<string>;\n signMessage(message: string | Uint8Array): Promise<string>;\n signTypedData(\n domain: unknown,\n types: Record<string, Array<{ name: string; type: string }>>,\n value: Record<string, unknown>\n ): Promise<string>;\n signTransaction(tx: unknown): Promise<string>;\n sendTransaction(tx: unknown): Promise<unknown>;\n connect(provider: unknown): EmblemEthersWallet;\n provider: unknown;\n // Additional methods\n initialize(): Promise<void>;\n getVaultId(): string;\n setChainId(chainId: number): void;\n getChainId(): number;\n signAndBroadcast(transaction: unknown, waitForReceipt?: boolean): Promise<string>;\n}\n\nexport async function toEthersWallet(\n config: SignerConfig,\n provider?: unknown | null,\n infoOverride?: SignerVaultInfo\n): Promise<EmblemEthersWallet> {\n // Dynamic import - only loads ethers when this function is called\n // String concatenation prevents bundlers from statically analyzing the import\n let ethers: typeof import('ethers');\n try {\n const moduleName = 'ethers';\n ethers = await import(/* @vite-ignore */ moduleName);\n } catch {\n throw new Error('ethers is required for toEthersWallet(). Install it with: npm install ethers');\n }\n\n const { AbstractSigner, resolveAddress } = ethers;\n type AbstractProvider = import('ethers').AbstractProvider;\n type TransactionRequest = import('ethers').TransactionRequest;\n type TransactionResponse = import('ethers').TransactionResponse;\n type TransactionLike = import('ethers').TransactionLike<string>;\n type TypedDataDomain = import('ethers').TypedDataDomain;\n type TypedDataField = import('ethers').TypedDataField;\n\n const info = infoOverride ?? (await fetchVaultInfo(config));\n\n // Class defined inside function after dynamic import\n class EmblemEthersWalletImpl extends AbstractSigner {\n private readonly _config: SignerConfig;\n private _address: Hex | null = null;\n private _vaultId: string | null = null;\n private _chainId = 1;\n private _initPromise?: Promise<void>;\n\n constructor(\n signerConfig: SignerConfig,\n signerProvider?: AbstractProvider | null,\n seed?: { address?: Hex; vaultId?: string; chainId?: number }\n ) {\n super(signerProvider ?? null);\n this._config = signerConfig;\n if (seed?.address) this._address = seed.address;\n if (seed?.vaultId) this._vaultId = seed.vaultId;\n if (seed?.chainId) this._chainId = seed.chainId;\n }\n\n async initialize(): Promise<void> {\n if (this._initPromise) return this._initPromise;\n\n this._initPromise = fetchVaultInfo(this._config)\n .then((vaultInfo) => {\n this._address = vaultInfo.evmAddress;\n this._vaultId = vaultInfo.vaultId;\n })\n .catch((err) => {\n this._initPromise = undefined;\n throw err;\n });\n\n return this._initPromise;\n }\n\n async getAddress(): Promise<string> {\n if (!this._address) await this.initialize();\n return this._address!;\n }\n\n getVaultId(): string {\n if (!this._vaultId) throw new Error('Wallet not initialized. Call initialize() first.');\n return this._vaultId;\n }\n\n setChainId(chainId: number): void {\n this._chainId = chainId;\n }\n\n getChainId(): number {\n return this._chainId;\n }\n\n connect(newProvider: AbstractProvider): EmblemEthersWalletImpl {\n if (!newProvider) throw new Error('Provider cannot be null');\n return new EmblemEthersWalletImpl(this._config, newProvider, {\n address: this._address ?? undefined,\n vaultId: this._vaultId ?? undefined,\n chainId: this._chainId,\n });\n }\n\n async signMessage(message: string | Uint8Array): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const payload = typeof message === 'string' ? message : bytesToHex(message);\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-eth-message',\n { vaultId: this._vaultId!, message: payload },\n this._config\n );\n return data.signature;\n }\n\n async signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const cleanTypes = { ...types };\n if (cleanTypes && (cleanTypes as Record<string, unknown>).EIP712Domain) {\n delete (cleanTypes as Record<string, unknown>).EIP712Domain;\n }\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-typed-message',\n { vaultId: this._vaultId!, domain, types: cleanTypes, message: value },\n this._config\n );\n return data.signature;\n }\n\n async _signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n return this.signTypedData(domain, types, value);\n }\n\n async signTransaction(tx: TransactionRequest): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const from = (tx as Record<string, unknown>).from as string | undefined;\n const addr = await this.getAddress();\n\n if (from && from.toLowerCase() !== addr.toLowerCase()) {\n throw new Error('transaction from does not match signer address');\n }\n\n const toSign = this.provider\n ? ({ ...await this.populateTransaction(tx) } as Record<string, unknown>)\n : ({ ...tx } as Record<string, unknown>);\n if (toSign.from) delete toSign.from;\n if (!('to' in toSign) || !toSign.to) {\n throw new Error(\"Transaction must have a 'to' address\");\n }\n if (toSign.nonce === undefined || toSign.nonce === null) {\n throw new Error('Transaction must have a nonce');\n }\n const normalized = normalizeTxForEmblem(toSign);\n const resp = await emblemPost<{ signedTransaction: Hex }>(\n '/sign-eth-tx',\n { vaultId: this._vaultId!, transaction: normalized, options: { chainId: this._chainId } },\n this._config\n );\n return resp.signedTransaction;\n }\n\n async sendTransaction(tx: TransactionRequest): Promise<TransactionResponse> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(tx);\n return await this.provider.broadcastTransaction(signed);\n }\n\n async populateTransaction(transaction: TransactionRequest): Promise<TransactionLike> {\n const tx = { ...transaction } as TransactionRequest;\n if (!this.provider) throw new Error('Provider required to populate transaction');\n const fromAddress = tx.from\n ? await resolveAddress(tx.from, this.provider)\n : await this.getAddress();\n\n let chainId: bigint;\n if (!tx.chainId) {\n const network = await this.provider.getNetwork();\n chainId = network.chainId;\n this._chainId = Number(network.chainId);\n } else {\n chainId = BigInt(tx.chainId);\n this._chainId = Number(tx.chainId);\n }\n\n const nonce =\n tx.nonce != null\n ? Number(tx.nonce)\n : await this.provider.getTransactionCount(fromAddress, 'pending');\n const toAddress = tx.to ? await resolveAddress(tx.to, this.provider) : null;\n const value = tx.value ? BigInt(tx.value.toString()) : 0n;\n\n let gasLimit: bigint;\n if (!tx.gasLimit) {\n try {\n gasLimit = await this.provider.estimateGas({ ...tx, from: fromAddress });\n } catch {\n gasLimit = 21000n;\n }\n } else {\n gasLimit = BigInt(tx.gasLimit.toString());\n }\n\n let gasPrice: bigint | null = null;\n if (!tx.gasPrice && tx.type !== 2) {\n const feeData = await this.provider.getFeeData();\n gasPrice = feeData.gasPrice ?? null;\n } else if (tx.gasPrice) {\n gasPrice = BigInt(tx.gasPrice.toString());\n }\n\n const populated: TransactionLike = {\n from: fromAddress,\n to: toAddress,\n value,\n nonce,\n gasLimit,\n data: tx.data as string | undefined,\n chainId,\n type: tx.type || undefined,\n };\n if (gasPrice !== null) populated.gasPrice = gasPrice;\n if (tx.maxFeePerGas) populated.maxFeePerGas = BigInt(tx.maxFeePerGas.toString());\n if (tx.maxPriorityFeePerGas)\n populated.maxPriorityFeePerGas = BigInt(tx.maxPriorityFeePerGas.toString());\n return populated;\n }\n\n async signAndBroadcast(\n transaction: TransactionRequest,\n waitForReceipt: boolean = false\n ): Promise<string> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(transaction);\n const resp = await this.provider.broadcastTransaction(signed);\n const hash = resp.hash as string;\n if (waitForReceipt) {\n await this.provider.waitForTransaction(hash);\n }\n return hash;\n }\n }\n\n return new EmblemEthersWalletImpl(config, provider as AbstractProvider | null, {\n address: info.evmAddress,\n vaultId: info.vaultId,\n });\n}\n"],"names":["async","emblemPost","path","body","config","baseUrl","authHeaders","getAuthHeaders","h","tok","jwt","getJwt","undefined","sdk","getSession","authToken","Authorization","apiKey","Error","resolveAuthHeaders","res","fetch","method","headers","JSON","stringify","_key","value","toString","ok","text","catch","status","errorMessage","substring","sanitizeErrorMessage","json","toSafeNumber","fieldName","num","Number","isSafeInteger","MAX_SAFE_INTEGER","toHexIfBigInt","v","fetchVaultInfo","data","vaultId","evmAddress","String","startsWith","tokenId","address","created_by","provider","infoOverride","ethers","moduleName","AbstractSigner","resolveAddress","info","EmblemEthersWalletImpl","constructor","signerConfig","signerProvider","seed","super","this","_address","_vaultId","_chainId","_config","chainId","initialize","_initPromise","then","vaultInfo","err","getAddress","getVaultId","setChainId","getChainId","connect","newProvider","signMessage","message","payload","bytes","out","i","length","padStart","bytesToHex","signature","signTypedData","domain","types","cleanTypes","EIP712Domain","_signTypedData","signTransaction","tx","from","addr","toLowerCase","toSign","populateTransaction","to","nonce","normalized","gas","gasLimit","gasPrice","maxFeePerGas","maxPriorityFeePerGas","type","accessList","account","chain","normalizeTxForEmblem","transaction","options","signedTransaction","sendTransaction","signed","broadcastTransaction","fromAddress","BigInt","network","getNetwork","getTransactionCount","toAddress","estimateGas","getFeeData","populated","signAndBroadcast","waitForReceipt","hash","waitForTransaction"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- async function t(t,e,i){const a=i.baseUrl??"https://api.emblemvault.ai",r=await async function(t){if("function"==typeof t.getAuthHeaders){const e=await t.getAuthHeaders();if(e&&"object"==typeof e)return e}const e=t.jwt??("function"==typeof t.getJwt?await t.getJwt():void 0)??t.sdk?.getSession()?.authToken??void 0;if(e)return{Authorization:`Bearer ${e}`};if(t.apiKey)return{"x-api-key":t.apiKey};throw new Error("No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey")}(i),s=await fetch(`${a}${t}`,{method:"POST",headers:{"content-type":"application/json",...r},body:JSON.stringify(e,(t,e)=>"bigint"==typeof e?e.toString():e)});if(!s.ok){const t=await s.text().catch(()=>"");throw new Error(function(t,e){let i=`Emblem signer error ${t}`;return t>=500?i+=": Internal server error":401===t||403===t?i+=": Authentication failed":404===t?i+=": Resource not found":405===t?i+=": Method not allowed":e&&(i+=`: ${e.substring(0,200)}`),i}(s.status,t))}return s.json()}function e(t,e){const i=Number(t);if(!Number.isSafeInteger(i))throw new Error(`${e} value ${t} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`);return i}function i(t){return"bigint"==typeof t?"0x"+t.toString(16):t}async function a(e){const i=await t("/vault/info",{},e);if(!i||!i.vaultId||!i.evmAddress)throw new Error("Invalid vault info response: missing required fields");if(!String(i.evmAddress).startsWith("0x"))throw new Error("Invalid evmAddress format in response");return{vaultId:i.vaultId,tokenId:i.vaultId,address:i.address||"",evmAddress:i.evmAddress,created_by:i.created_by}}async function r(r,s,n){let o;try{o=await import("ethers")}catch{throw new Error("ethers is required for toEthersWallet(). Install it with: npm install ethers")}const{AbstractSigner:d,resolveAddress:c}=o,h=n??await a(r);class u extends d{constructor(t,e,i){super(e??null),this._address=null,this._vaultId=null,this._chainId=1,this._config=t,i?.address&&(this._address=i.address),i?.vaultId&&(this._vaultId=i.vaultId),i?.chainId&&(this._chainId=i.chainId)}async initialize(){return this._initPromise||(this._initPromise=a(this._config).then(t=>{this._address=t.evmAddress,this._vaultId=t.vaultId}).catch(t=>{throw this._initPromise=void 0,t})),this._initPromise}async getAddress(){return this._address||await this.initialize(),this._address}getVaultId(){if(!this._vaultId)throw new Error("Wallet not initialized. Call initialize() first.");return this._vaultId}setChainId(t){this._chainId=t}getChainId(){return this._chainId}connect(t){if(!t)throw new Error("Provider cannot be null");return new u(this._config,t,{address:this._address??void 0,vaultId:this._vaultId??void 0,chainId:this._chainId})}async signMessage(e){this._vaultId||await this.initialize();const i="string"==typeof e?e:function(t){let e="0x";for(let i=0;i<t.length;i++)e+=t[i].toString(16).padStart(2,"0");return e}(e);return(await t("/sign-eth-message",{vaultId:this._vaultId,message:i},this._config)).signature}async signTypedData(e,i,a){this._vaultId||await this.initialize();const r={...i};r&&r.EIP712Domain&&delete r.EIP712Domain;return(await t("/sign-typed-message",{vaultId:this._vaultId,domain:e,types:r,message:a},this._config)).signature}async _signTypedData(t,e,i){return this.signTypedData(t,e,i)}async signTransaction(a){this._vaultId||await this.initialize();const r=a.from,s=await this.getAddress();if(r&&r.toLowerCase()!==s.toLowerCase())throw new Error("transaction from does not match signer address");const n=this.provider?{...await this.populateTransaction(a)}:{...a};if(n.from&&delete n.from,!("to"in n)||!n.to)throw new Error("Transaction must have a 'to' address");if(void 0===n.nonce||null===n.nonce)throw new Error("Transaction must have a nonce");const o=function(t){const a={...t};return void 0!==a.value&&(a.value=i(a.value)),void 0!==a.gas&&(a.gasLimit=i(a.gas),delete a.gas),void 0!==a.gasLimit&&(a.gasLimit=i(a.gasLimit)),void 0!==a.gasPrice&&(a.gasPrice=i(a.gasPrice)),void 0!==a.maxFeePerGas&&(a.maxFeePerGas=i(a.maxFeePerGas)),void 0!==a.maxPriorityFeePerGas&&(a.maxPriorityFeePerGas=i(a.maxPriorityFeePerGas)),void 0!==a.nonce&&(a.nonce=e(a.nonce,"nonce")),void 0!==a.chainId&&(a.chainId=e(a.chainId,"chainId")),void 0===a.maxFeePerGas&&void 0===a.maxPriorityFeePerGas||(void 0===a.gasPrice&&void 0!==a.maxFeePerGas&&(a.gasPrice=a.maxFeePerGas),delete a.maxFeePerGas,delete a.maxPriorityFeePerGas),delete a.type,delete a.accessList,delete a.account,delete a.chain,delete a.from,a}(n);return(await t("/sign-eth-tx",{vaultId:this._vaultId,transaction:o,options:{chainId:this._chainId}},this._config)).signedTransaction}async sendTransaction(t){if(!this.provider)throw new Error("Provider required to send transaction");const e=await this.signTransaction(t);return await this.provider.broadcastTransaction(e)}async populateTransaction(t){const e={...t};if(!this.provider)throw new Error("Provider required to populate transaction");const i=e.from?await c(e.from,this.provider):await this.getAddress();let a;if(e.chainId)a=BigInt(e.chainId),this._chainId=Number(e.chainId);else{const t=await this.provider.getNetwork();a=t.chainId,this._chainId=Number(t.chainId)}const r=null!=e.nonce?Number(e.nonce):await this.provider.getTransactionCount(i,"pending"),s=e.to?await c(e.to,this.provider):null,n=e.value?BigInt(e.value.toString()):0n;let o;if(e.gasLimit)o=BigInt(e.gasLimit.toString());else try{o=await this.provider.estimateGas({...e,from:i})}catch{o=21000n}let d=null;if(e.gasPrice||2===e.type)e.gasPrice&&(d=BigInt(e.gasPrice.toString()));else{d=(await this.provider.getFeeData()).gasPrice??null}const h={from:i,to:s,value:n,nonce:r,gasLimit:o,data:e.data,chainId:a,type:e.type||void 0};return null!==d&&(h.gasPrice=d),e.maxFeePerGas&&(h.maxFeePerGas=BigInt(e.maxFeePerGas.toString())),e.maxPriorityFeePerGas&&(h.maxPriorityFeePerGas=BigInt(e.maxPriorityFeePerGas.toString())),h}async signAndBroadcast(t,e=!1){if(!this.provider)throw new Error("Provider required to send transaction");const i=await this.signTransaction(t),a=(await this.provider.broadcastTransaction(i)).hash;return e&&await this.provider.waitForTransaction(a),a}}return new u(r,s,{address:h.evmAddress,vaultId:h.vaultId})}export{r as toEthersWallet};
1
+ async function t(t,e,i){const a=i.baseUrl??"https://api.emblemvault.ai",r=await async function(t){if("function"==typeof t.getAuthHeaders){const e=await t.getAuthHeaders();if(e&&"object"==typeof e)return e}const e=t.jwt??("function"==typeof t.getJwt?await t.getJwt():void 0)??t.sdk?.getSession()?.authToken??void 0;if(e)return{Authorization:`Bearer ${e}`};if(t.apiKey)return{"x-api-key":t.apiKey};throw new Error("No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey")}(i),s=await fetch(`${a}${t}`,{method:"POST",headers:{"content-type":"application/json",...r},body:JSON.stringify(e,(t,e)=>"bigint"==typeof e?e.toString():e)});if(!s.ok){const t=await s.text().catch(()=>"");throw new Error(function(t,e){let i=`Emblem signer error ${t}`;return t>=500?i+=": Internal server error":401===t||403===t?i+=": Authentication failed":404===t?i+=": Resource not found":405===t?i+=": Method not allowed":e&&(i+=`: ${e.substring(0,200)}`),i}(s.status,t))}return s.json()}function e(t,e){const i=Number(t);if(!Number.isSafeInteger(i))throw new Error(`${e} value ${t} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`);return i}function i(t){return"bigint"==typeof t?"0x"+t.toString(16):t}async function a(e){const i=await t("/vault/info",{},e);if(!i||!i.vaultId||!i.evmAddress)throw new Error("Invalid vault info response: missing required fields");if(!String(i.evmAddress).startsWith("0x"))throw new Error("Invalid evmAddress format in response");return{vaultId:i.vaultId,tokenId:i.vaultId,address:i.address||"",evmAddress:i.evmAddress,created_by:i.created_by}}async function r(r,s,n){let o;try{const t="ethers";o=await import(t)}catch{throw new Error("ethers is required for toEthersWallet(). Install it with: npm install ethers")}const{AbstractSigner:d,resolveAddress:c}=o,h=n??await a(r);class u extends d{constructor(t,e,i){super(e??null),this._address=null,this._vaultId=null,this._chainId=1,this._config=t,i?.address&&(this._address=i.address),i?.vaultId&&(this._vaultId=i.vaultId),i?.chainId&&(this._chainId=i.chainId)}async initialize(){return this._initPromise||(this._initPromise=a(this._config).then(t=>{this._address=t.evmAddress,this._vaultId=t.vaultId}).catch(t=>{throw this._initPromise=void 0,t})),this._initPromise}async getAddress(){return this._address||await this.initialize(),this._address}getVaultId(){if(!this._vaultId)throw new Error("Wallet not initialized. Call initialize() first.");return this._vaultId}setChainId(t){this._chainId=t}getChainId(){return this._chainId}connect(t){if(!t)throw new Error("Provider cannot be null");return new u(this._config,t,{address:this._address??void 0,vaultId:this._vaultId??void 0,chainId:this._chainId})}async signMessage(e){this._vaultId||await this.initialize();const i="string"==typeof e?e:function(t){let e="0x";for(let i=0;i<t.length;i++)e+=t[i].toString(16).padStart(2,"0");return e}(e);return(await t("/sign-eth-message",{vaultId:this._vaultId,message:i},this._config)).signature}async signTypedData(e,i,a){this._vaultId||await this.initialize();const r={...i};r&&r.EIP712Domain&&delete r.EIP712Domain;return(await t("/sign-typed-message",{vaultId:this._vaultId,domain:e,types:r,message:a},this._config)).signature}async _signTypedData(t,e,i){return this.signTypedData(t,e,i)}async signTransaction(a){this._vaultId||await this.initialize();const r=a.from,s=await this.getAddress();if(r&&r.toLowerCase()!==s.toLowerCase())throw new Error("transaction from does not match signer address");const n=this.provider?{...await this.populateTransaction(a)}:{...a};if(n.from&&delete n.from,!("to"in n)||!n.to)throw new Error("Transaction must have a 'to' address");if(void 0===n.nonce||null===n.nonce)throw new Error("Transaction must have a nonce");const o=function(t){const a={...t};return void 0!==a.value&&(a.value=i(a.value)),void 0!==a.gas&&(a.gasLimit=i(a.gas),delete a.gas),void 0!==a.gasLimit&&(a.gasLimit=i(a.gasLimit)),void 0!==a.gasPrice&&(a.gasPrice=i(a.gasPrice)),void 0!==a.maxFeePerGas&&(a.maxFeePerGas=i(a.maxFeePerGas)),void 0!==a.maxPriorityFeePerGas&&(a.maxPriorityFeePerGas=i(a.maxPriorityFeePerGas)),void 0!==a.nonce&&(a.nonce=e(a.nonce,"nonce")),void 0!==a.chainId&&(a.chainId=e(a.chainId,"chainId")),void 0===a.maxFeePerGas&&void 0===a.maxPriorityFeePerGas||(void 0===a.gasPrice&&void 0!==a.maxFeePerGas&&(a.gasPrice=a.maxFeePerGas),delete a.maxFeePerGas,delete a.maxPriorityFeePerGas),delete a.type,delete a.accessList,delete a.account,delete a.chain,delete a.from,a}(n);return(await t("/sign-eth-tx",{vaultId:this._vaultId,transaction:o,options:{chainId:this._chainId}},this._config)).signedTransaction}async sendTransaction(t){if(!this.provider)throw new Error("Provider required to send transaction");const e=await this.signTransaction(t);return await this.provider.broadcastTransaction(e)}async populateTransaction(t){const e={...t};if(!this.provider)throw new Error("Provider required to populate transaction");const i=e.from?await c(e.from,this.provider):await this.getAddress();let a;if(e.chainId)a=BigInt(e.chainId),this._chainId=Number(e.chainId);else{const t=await this.provider.getNetwork();a=t.chainId,this._chainId=Number(t.chainId)}const r=null!=e.nonce?Number(e.nonce):await this.provider.getTransactionCount(i,"pending"),s=e.to?await c(e.to,this.provider):null,n=e.value?BigInt(e.value.toString()):0n;let o;if(e.gasLimit)o=BigInt(e.gasLimit.toString());else try{o=await this.provider.estimateGas({...e,from:i})}catch{o=21000n}let d=null;if(e.gasPrice||2===e.type)e.gasPrice&&(d=BigInt(e.gasPrice.toString()));else{d=(await this.provider.getFeeData()).gasPrice??null}const h={from:i,to:s,value:n,nonce:r,gasLimit:o,data:e.data,chainId:a,type:e.type||void 0};return null!==d&&(h.gasPrice=d),e.maxFeePerGas&&(h.maxFeePerGas=BigInt(e.maxFeePerGas.toString())),e.maxPriorityFeePerGas&&(h.maxPriorityFeePerGas=BigInt(e.maxPriorityFeePerGas.toString())),h}async signAndBroadcast(t,e=!1){if(!this.provider)throw new Error("Provider required to send transaction");const i=await this.signTransaction(t),a=(await this.provider.broadcastTransaction(i)).hash;return e&&await this.provider.waitForTransaction(a),a}}return new u(r,s,{address:h.evmAddress,vaultId:h.vaultId})}export{r as toEthersWallet};
2
2
  //# sourceMappingURL=ethers.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ethers.mjs","sources":["../../src/signers/http.ts","../../src/signers/validation.ts","../../src/signers/utils.ts","../../src/signers/vault.ts","../../src/signers/ethers.ts"],"sourcesContent":["import type { SignerConfig } from '../types/signers';\n\nfunction sanitizeErrorMessage(status: number, text: string): string {\n // Sanitize error messages to avoid leaking sensitive server information\n let errorMessage = `Emblem signer error ${status}`;\n\n if (status >= 500) {\n errorMessage += ': Internal server error';\n } else if (status === 401 || status === 403) {\n errorMessage += ': Authentication failed';\n } else if (status === 404) {\n errorMessage += ': Resource not found';\n } else if (status === 405) {\n errorMessage += ': Method not allowed';\n } else if (text) {\n // For 4xx client errors, include limited error details\n errorMessage += `: ${text.substring(0, 200)}`; // Limit to 200 chars\n }\n\n return errorMessage;\n}\n\nasync function resolveAuthHeaders(config: SignerConfig): Promise<Record<string, string>> {\n // Priority: custom headers -> jwt/getJwt/sdk -> apiKey (deprecated)\n if (typeof config.getAuthHeaders === 'function') {\n const h = await config.getAuthHeaders();\n if (h && typeof h === 'object') return h;\n }\n\n const tok =\n config.jwt ??\n (typeof config.getJwt === 'function' ? await config.getJwt() : undefined) ??\n config.sdk?.getSession()?.authToken ??\n undefined;\n\n if (tok) {\n return { Authorization: `Bearer ${tok}` };\n }\n\n // apiKey is deprecated but still supported as fallback\n if (config.apiKey) {\n return { 'x-api-key': config.apiKey };\n }\n\n throw new Error(\n 'No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey'\n );\n}\n\nexport async function emblemPost<T = unknown>(\n path: string,\n body: unknown,\n config: SignerConfig\n): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n ...authHeaders,\n },\n body: JSON.stringify(body, (_key: string, value: unknown) =>\n typeof value === 'bigint' ? value.toString() : value\n ),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n\nexport async function emblemGet<T = unknown>(path: string, config: SignerConfig): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'GET',\n headers: authHeaders,\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n","import type { SignerConfig } from '../types/signers';\n\n/**\n * Environment detection utilities for warning about unsafe usage patterns\n */\n\n/**\n * Detect if code is running in a browser environment\n */\nexport function isBrowserEnvironment(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if we're in a Node.js server environment\n */\nexport function isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' && process.versions != null && process.versions.node != null\n );\n}\n\n/**\n * Validate baseUrl format\n */\nexport function validateBaseUrl(baseUrl?: string): void {\n if (!baseUrl) return; // undefined is ok, will use default\n\n if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {\n throw new Error('baseUrl must be a valid HTTP(S) URL');\n }\n\n // Warn about http (not https)\n if (\n baseUrl.startsWith('http://') &&\n !baseUrl.includes('localhost') &&\n !baseUrl.includes('127.0.0.1')\n ) {\n console.warn(\n '[Emblem Security Warning] baseUrl uses HTTP instead of HTTPS. This is insecure for production use.'\n );\n }\n}\n\n/**\n * Validate Ethereum address format\n */\nexport function validateEthereumAddress(address: string): void {\n if (!address || typeof address !== 'string') {\n throw new Error('Address is required');\n }\n\n if (!address.startsWith('0x')) {\n throw new Error('Address must start with 0x');\n }\n\n if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {\n throw new Error('Invalid Ethereum address format');\n }\n}\n\n/**\n * Validate vault ID\n */\nexport function validateVaultId(vaultId: string): void {\n if (!vaultId || typeof vaultId !== 'string') {\n throw new Error('vaultId is required');\n }\n\n if (vaultId.trim() === '') {\n throw new Error('vaultId cannot be empty');\n }\n}\n\n/**\n * Safe number conversion with bounds checking\n */\nexport function toSafeNumber(value: unknown, fieldName: string): number {\n const num = Number(value);\n\n if (!Number.isSafeInteger(num)) {\n throw new Error(\n `${fieldName} value ${value} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`\n );\n }\n\n return num;\n}\n\n/**\n * Extended config with security options\n */\nexport interface SignerSecurityConfig extends SignerConfig {\n /**\n * Enable debug logging for security-related checks\n * @default false\n */\n debugSecurity?: boolean;\n}\n\n/**\n * Validate signer configuration\n */\nexport function validateSignerConfig(config: SignerSecurityConfig): void {\n // Validate auth: require at least one method (jwt, getJwt, getAuthHeaders)\n const hasJwt = !!config.jwt;\n const hasGetJwt = typeof config.getJwt === 'function';\n const hasHeaders = typeof config.getAuthHeaders === 'function';\n\n if (!hasJwt && !hasGetJwt && !hasHeaders) {\n throw new Error('Authentication required: provide jwt, getJwt(), or getAuthHeaders()');\n }\n\n // Validate baseUrl if provided\n if (config.baseUrl) {\n validateBaseUrl(config.baseUrl);\n }\n\n // Security audit logging\n if (config.debugSecurity) {\n console.log('[Emblem Security Debug]', {\n environment: isBrowserEnvironment() ? 'browser' : 'node',\n hasBaseUrl: !!config.baseUrl,\n timestamp: new Date().toISOString(),\n });\n }\n}\n","import type { Hex } from '../types/signers';\nimport { toSafeNumber } from './validation';\n\nexport function toHexIfBigInt(v: unknown): unknown {\n return typeof v === 'bigint' ? '0x' + v.toString(16) : v;\n}\n\n/**\n * viem txs sometimes have bigint / hex / optional fields. Ethers serializers\n * accept hex strings for numeric fields. Normalize where helpful.\n */\nexport function normalizeTxForEmblem(tx: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...tx };\n\n if (out.value !== undefined) out.value = toHexIfBigInt(out.value);\n if (out.gas !== undefined) {\n out.gasLimit = toHexIfBigInt(out.gas);\n delete out.gas;\n }\n if (out.gasLimit !== undefined) out.gasLimit = toHexIfBigInt(out.gasLimit);\n if (out.gasPrice !== undefined) out.gasPrice = toHexIfBigInt(out.gasPrice);\n if (out.maxFeePerGas !== undefined) out.maxFeePerGas = toHexIfBigInt(out.maxFeePerGas);\n if (out.maxPriorityFeePerGas !== undefined)\n out.maxPriorityFeePerGas = toHexIfBigInt(out.maxPriorityFeePerGas);\n if (out.nonce !== undefined) out.nonce = toSafeNumber(out.nonce, 'nonce');\n if (out.chainId !== undefined) out.chainId = toSafeNumber(out.chainId, 'chainId');\n\n // Some backends only accept legacy fields; fold EIP-1559 into gasPrice and drop unsupported keys\n if (out.maxFeePerGas !== undefined || out.maxPriorityFeePerGas !== undefined) {\n if (out.gasPrice === undefined && out.maxFeePerGas !== undefined) {\n out.gasPrice = out.maxFeePerGas;\n }\n delete out.maxFeePerGas;\n delete out.maxPriorityFeePerGas;\n }\n\n // Remove fields commonly unsupported by legacy serializers\n delete out.type;\n delete out.accessList;\n delete out.account;\n delete out.chain;\n delete out.from;\n\n return out;\n}\n\nexport function isHexString(value: unknown): value is Hex {\n return typeof value === 'string' && /^0x[0-9a-fA-F]*$/.test(value);\n}\n\nexport function bytesToHex(bytes: ArrayLike<number>): Hex {\n let out = '0x';\n for (let i = 0; i < bytes.length; i++) {\n out += (bytes[i] as number).toString(16).padStart(2, '0');\n }\n return out as Hex;\n}\n","import type { SignerConfig, SignerVaultInfo, Hex } from '../types/signers';\nimport { emblemPost } from './http';\n\nexport async function fetchVaultInfo(config: SignerConfig): Promise<SignerVaultInfo> {\n // Note: The server only supports POST for /vault/info\n const data: Partial<{\n vaultId: string;\n address: string;\n evmAddress: Hex;\n created_by?: string;\n }> = await emblemPost('/vault/info', {}, config);\n\n // Validate required response data (vaultId + evmAddress are required for EVM)\n if (!data || !data.vaultId || !data.evmAddress) {\n throw new Error('Invalid vault info response: missing required fields');\n }\n\n if (!String(data.evmAddress).startsWith('0x')) {\n throw new Error('Invalid evmAddress format in response');\n }\n\n return {\n vaultId: data.vaultId,\n tokenId: data.vaultId,\n address: data.address || '', // Solana address may be absent; keep optional\n evmAddress: data.evmAddress as Hex,\n created_by: data.created_by,\n };\n}\n","import type { Hex, SignerConfig, SignerVaultInfo } from '../types/signers';\nimport { emblemPost } from './http';\nimport { bytesToHex, normalizeTxForEmblem } from './utils';\nimport { fetchVaultInfo } from './vault';\n\n// ethers v6 compatible interface (like solana pattern - no runtime dependency)\nexport interface EmblemEthersWallet {\n getAddress(): Promise<string>;\n signMessage(message: string | Uint8Array): Promise<string>;\n signTypedData(\n domain: unknown,\n types: Record<string, Array<{ name: string; type: string }>>,\n value: Record<string, unknown>\n ): Promise<string>;\n signTransaction(tx: unknown): Promise<string>;\n sendTransaction(tx: unknown): Promise<unknown>;\n connect(provider: unknown): EmblemEthersWallet;\n provider: unknown;\n // Additional methods\n initialize(): Promise<void>;\n getVaultId(): string;\n setChainId(chainId: number): void;\n getChainId(): number;\n signAndBroadcast(transaction: unknown, waitForReceipt?: boolean): Promise<string>;\n}\n\nexport async function toEthersWallet(\n config: SignerConfig,\n provider?: unknown | null,\n infoOverride?: SignerVaultInfo\n): Promise<EmblemEthersWallet> {\n // Dynamic import - only loads ethers when this function is called\n // webpackIgnore comment prevents webpack from trying to resolve at build time\n let ethers: typeof import('ethers');\n try {\n ethers = await import(/* webpackIgnore: true */ 'ethers');\n } catch {\n throw new Error('ethers is required for toEthersWallet(). Install it with: npm install ethers');\n }\n\n const { AbstractSigner, resolveAddress } = ethers;\n type AbstractProvider = import('ethers').AbstractProvider;\n type TransactionRequest = import('ethers').TransactionRequest;\n type TransactionResponse = import('ethers').TransactionResponse;\n type TransactionLike = import('ethers').TransactionLike<string>;\n type TypedDataDomain = import('ethers').TypedDataDomain;\n type TypedDataField = import('ethers').TypedDataField;\n\n const info = infoOverride ?? (await fetchVaultInfo(config));\n\n // Class defined inside function after dynamic import\n class EmblemEthersWalletImpl extends AbstractSigner {\n private readonly _config: SignerConfig;\n private _address: Hex | null = null;\n private _vaultId: string | null = null;\n private _chainId = 1;\n private _initPromise?: Promise<void>;\n\n constructor(\n signerConfig: SignerConfig,\n signerProvider?: AbstractProvider | null,\n seed?: { address?: Hex; vaultId?: string; chainId?: number }\n ) {\n super(signerProvider ?? null);\n this._config = signerConfig;\n if (seed?.address) this._address = seed.address;\n if (seed?.vaultId) this._vaultId = seed.vaultId;\n if (seed?.chainId) this._chainId = seed.chainId;\n }\n\n async initialize(): Promise<void> {\n if (this._initPromise) return this._initPromise;\n\n this._initPromise = fetchVaultInfo(this._config)\n .then((vaultInfo) => {\n this._address = vaultInfo.evmAddress;\n this._vaultId = vaultInfo.vaultId;\n })\n .catch((err) => {\n this._initPromise = undefined;\n throw err;\n });\n\n return this._initPromise;\n }\n\n async getAddress(): Promise<string> {\n if (!this._address) await this.initialize();\n return this._address!;\n }\n\n getVaultId(): string {\n if (!this._vaultId) throw new Error('Wallet not initialized. Call initialize() first.');\n return this._vaultId;\n }\n\n setChainId(chainId: number): void {\n this._chainId = chainId;\n }\n\n getChainId(): number {\n return this._chainId;\n }\n\n connect(newProvider: AbstractProvider): EmblemEthersWalletImpl {\n if (!newProvider) throw new Error('Provider cannot be null');\n return new EmblemEthersWalletImpl(this._config, newProvider, {\n address: this._address ?? undefined,\n vaultId: this._vaultId ?? undefined,\n chainId: this._chainId,\n });\n }\n\n async signMessage(message: string | Uint8Array): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const payload = typeof message === 'string' ? message : bytesToHex(message);\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-eth-message',\n { vaultId: this._vaultId!, message: payload },\n this._config\n );\n return data.signature;\n }\n\n async signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const cleanTypes = { ...types };\n if (cleanTypes && (cleanTypes as Record<string, unknown>).EIP712Domain) {\n delete (cleanTypes as Record<string, unknown>).EIP712Domain;\n }\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-typed-message',\n { vaultId: this._vaultId!, domain, types: cleanTypes, message: value },\n this._config\n );\n return data.signature;\n }\n\n async _signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n return this.signTypedData(domain, types, value);\n }\n\n async signTransaction(tx: TransactionRequest): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const from = (tx as Record<string, unknown>).from as string | undefined;\n const addr = await this.getAddress();\n\n if (from && from.toLowerCase() !== addr.toLowerCase()) {\n throw new Error('transaction from does not match signer address');\n }\n\n const toSign = this.provider\n ? ({ ...await this.populateTransaction(tx) } as Record<string, unknown>)\n : ({ ...tx } as Record<string, unknown>);\n if (toSign.from) delete toSign.from;\n if (!('to' in toSign) || !toSign.to) {\n throw new Error(\"Transaction must have a 'to' address\");\n }\n if (toSign.nonce === undefined || toSign.nonce === null) {\n throw new Error('Transaction must have a nonce');\n }\n const normalized = normalizeTxForEmblem(toSign);\n const resp = await emblemPost<{ signedTransaction: Hex }>(\n '/sign-eth-tx',\n { vaultId: this._vaultId!, transaction: normalized, options: { chainId: this._chainId } },\n this._config\n );\n return resp.signedTransaction;\n }\n\n async sendTransaction(tx: TransactionRequest): Promise<TransactionResponse> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(tx);\n return await this.provider.broadcastTransaction(signed);\n }\n\n async populateTransaction(transaction: TransactionRequest): Promise<TransactionLike> {\n const tx = { ...transaction } as TransactionRequest;\n if (!this.provider) throw new Error('Provider required to populate transaction');\n const fromAddress = tx.from\n ? await resolveAddress(tx.from, this.provider)\n : await this.getAddress();\n\n let chainId: bigint;\n if (!tx.chainId) {\n const network = await this.provider.getNetwork();\n chainId = network.chainId;\n this._chainId = Number(network.chainId);\n } else {\n chainId = BigInt(tx.chainId);\n this._chainId = Number(tx.chainId);\n }\n\n const nonce =\n tx.nonce != null\n ? Number(tx.nonce)\n : await this.provider.getTransactionCount(fromAddress, 'pending');\n const toAddress = tx.to ? await resolveAddress(tx.to, this.provider) : null;\n const value = tx.value ? BigInt(tx.value.toString()) : 0n;\n\n let gasLimit: bigint;\n if (!tx.gasLimit) {\n try {\n gasLimit = await this.provider.estimateGas({ ...tx, from: fromAddress });\n } catch {\n gasLimit = 21000n;\n }\n } else {\n gasLimit = BigInt(tx.gasLimit.toString());\n }\n\n let gasPrice: bigint | null = null;\n if (!tx.gasPrice && tx.type !== 2) {\n const feeData = await this.provider.getFeeData();\n gasPrice = feeData.gasPrice ?? null;\n } else if (tx.gasPrice) {\n gasPrice = BigInt(tx.gasPrice.toString());\n }\n\n const populated: TransactionLike = {\n from: fromAddress,\n to: toAddress,\n value,\n nonce,\n gasLimit,\n data: tx.data as string | undefined,\n chainId,\n type: tx.type || undefined,\n };\n if (gasPrice !== null) populated.gasPrice = gasPrice;\n if (tx.maxFeePerGas) populated.maxFeePerGas = BigInt(tx.maxFeePerGas.toString());\n if (tx.maxPriorityFeePerGas)\n populated.maxPriorityFeePerGas = BigInt(tx.maxPriorityFeePerGas.toString());\n return populated;\n }\n\n async signAndBroadcast(\n transaction: TransactionRequest,\n waitForReceipt: boolean = false\n ): Promise<string> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(transaction);\n const resp = await this.provider.broadcastTransaction(signed);\n const hash = resp.hash as string;\n if (waitForReceipt) {\n await this.provider.waitForTransaction(hash);\n }\n return hash;\n }\n }\n\n return new EmblemEthersWalletImpl(config, provider as AbstractProvider | null, {\n address: info.evmAddress,\n vaultId: info.vaultId,\n });\n}\n"],"names":["async","emblemPost","path","body","config","baseUrl","authHeaders","getAuthHeaders","h","tok","jwt","getJwt","undefined","sdk","getSession","authToken","Authorization","apiKey","Error","resolveAuthHeaders","res","fetch","method","headers","JSON","stringify","_key","value","toString","ok","text","catch","status","errorMessage","substring","sanitizeErrorMessage","json","toSafeNumber","fieldName","num","Number","isSafeInteger","MAX_SAFE_INTEGER","toHexIfBigInt","v","fetchVaultInfo","data","vaultId","evmAddress","String","startsWith","tokenId","address","created_by","toEthersWallet","provider","infoOverride","ethers","import","AbstractSigner","resolveAddress","info","EmblemEthersWalletImpl","constructor","signerConfig","signerProvider","seed","super","this","_address","_vaultId","_chainId","_config","chainId","initialize","_initPromise","then","vaultInfo","err","getAddress","getVaultId","setChainId","getChainId","connect","newProvider","signMessage","message","payload","bytes","out","i","length","padStart","bytesToHex","signature","signTypedData","domain","types","cleanTypes","EIP712Domain","_signTypedData","signTransaction","tx","from","addr","toLowerCase","toSign","populateTransaction","to","nonce","normalized","gas","gasLimit","gasPrice","maxFeePerGas","maxPriorityFeePerGas","type","accessList","account","chain","normalizeTxForEmblem","transaction","options","signedTransaction","sendTransaction","signed","broadcastTransaction","fromAddress","BigInt","network","getNetwork","getTransactionCount","toAddress","estimateGas","getFeeData","populated","signAndBroadcast","waitForReceipt","hash","waitForTransaction"],"mappings":"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"}
1
+ {"version":3,"file":"ethers.mjs","sources":["../../src/signers/http.ts","../../src/signers/validation.ts","../../src/signers/utils.ts","../../src/signers/vault.ts","../../src/signers/ethers.ts"],"sourcesContent":["import type { SignerConfig } from '../types/signers';\n\nfunction sanitizeErrorMessage(status: number, text: string): string {\n // Sanitize error messages to avoid leaking sensitive server information\n let errorMessage = `Emblem signer error ${status}`;\n\n if (status >= 500) {\n errorMessage += ': Internal server error';\n } else if (status === 401 || status === 403) {\n errorMessage += ': Authentication failed';\n } else if (status === 404) {\n errorMessage += ': Resource not found';\n } else if (status === 405) {\n errorMessage += ': Method not allowed';\n } else if (text) {\n // For 4xx client errors, include limited error details\n errorMessage += `: ${text.substring(0, 200)}`; // Limit to 200 chars\n }\n\n return errorMessage;\n}\n\nasync function resolveAuthHeaders(config: SignerConfig): Promise<Record<string, string>> {\n // Priority: custom headers -> jwt/getJwt/sdk -> apiKey (deprecated)\n if (typeof config.getAuthHeaders === 'function') {\n const h = await config.getAuthHeaders();\n if (h && typeof h === 'object') return h;\n }\n\n const tok =\n config.jwt ??\n (typeof config.getJwt === 'function' ? await config.getJwt() : undefined) ??\n config.sdk?.getSession()?.authToken ??\n undefined;\n\n if (tok) {\n return { Authorization: `Bearer ${tok}` };\n }\n\n // apiKey is deprecated but still supported as fallback\n if (config.apiKey) {\n return { 'x-api-key': config.apiKey };\n }\n\n throw new Error(\n 'No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey'\n );\n}\n\nexport async function emblemPost<T = unknown>(\n path: string,\n body: unknown,\n config: SignerConfig\n): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n ...authHeaders,\n },\n body: JSON.stringify(body, (_key: string, value: unknown) =>\n typeof value === 'bigint' ? value.toString() : value\n ),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n\nexport async function emblemGet<T = unknown>(path: string, config: SignerConfig): Promise<T> {\n const baseUrl = config.baseUrl ?? 'https://api.emblemvault.ai';\n const authHeaders = await resolveAuthHeaders(config);\n const res = await fetch(`${baseUrl}${path}`, {\n method: 'GET',\n headers: authHeaders,\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(sanitizeErrorMessage(res.status, text));\n }\n\n return res.json() as Promise<T>;\n}\n","import type { SignerConfig } from '../types/signers';\n\n/**\n * Environment detection utilities for warning about unsafe usage patterns\n */\n\n/**\n * Detect if code is running in a browser environment\n */\nexport function isBrowserEnvironment(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if we're in a Node.js server environment\n */\nexport function isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' && process.versions != null && process.versions.node != null\n );\n}\n\n/**\n * Validate baseUrl format\n */\nexport function validateBaseUrl(baseUrl?: string): void {\n if (!baseUrl) return; // undefined is ok, will use default\n\n if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {\n throw new Error('baseUrl must be a valid HTTP(S) URL');\n }\n\n // Warn about http (not https)\n if (\n baseUrl.startsWith('http://') &&\n !baseUrl.includes('localhost') &&\n !baseUrl.includes('127.0.0.1')\n ) {\n console.warn(\n '[Emblem Security Warning] baseUrl uses HTTP instead of HTTPS. This is insecure for production use.'\n );\n }\n}\n\n/**\n * Validate Ethereum address format\n */\nexport function validateEthereumAddress(address: string): void {\n if (!address || typeof address !== 'string') {\n throw new Error('Address is required');\n }\n\n if (!address.startsWith('0x')) {\n throw new Error('Address must start with 0x');\n }\n\n if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {\n throw new Error('Invalid Ethereum address format');\n }\n}\n\n/**\n * Validate vault ID\n */\nexport function validateVaultId(vaultId: string): void {\n if (!vaultId || typeof vaultId !== 'string') {\n throw new Error('vaultId is required');\n }\n\n if (vaultId.trim() === '') {\n throw new Error('vaultId cannot be empty');\n }\n}\n\n/**\n * Safe number conversion with bounds checking\n */\nexport function toSafeNumber(value: unknown, fieldName: string): number {\n const num = Number(value);\n\n if (!Number.isSafeInteger(num)) {\n throw new Error(\n `${fieldName} value ${value} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`\n );\n }\n\n return num;\n}\n\n/**\n * Extended config with security options\n */\nexport interface SignerSecurityConfig extends SignerConfig {\n /**\n * Enable debug logging for security-related checks\n * @default false\n */\n debugSecurity?: boolean;\n}\n\n/**\n * Validate signer configuration\n */\nexport function validateSignerConfig(config: SignerSecurityConfig): void {\n // Validate auth: require at least one method (jwt, getJwt, getAuthHeaders)\n const hasJwt = !!config.jwt;\n const hasGetJwt = typeof config.getJwt === 'function';\n const hasHeaders = typeof config.getAuthHeaders === 'function';\n\n if (!hasJwt && !hasGetJwt && !hasHeaders) {\n throw new Error('Authentication required: provide jwt, getJwt(), or getAuthHeaders()');\n }\n\n // Validate baseUrl if provided\n if (config.baseUrl) {\n validateBaseUrl(config.baseUrl);\n }\n\n // Security audit logging\n if (config.debugSecurity) {\n console.log('[Emblem Security Debug]', {\n environment: isBrowserEnvironment() ? 'browser' : 'node',\n hasBaseUrl: !!config.baseUrl,\n timestamp: new Date().toISOString(),\n });\n }\n}\n","import type { Hex } from '../types/signers';\nimport { toSafeNumber } from './validation';\n\nexport function toHexIfBigInt(v: unknown): unknown {\n return typeof v === 'bigint' ? '0x' + v.toString(16) : v;\n}\n\n/**\n * viem txs sometimes have bigint / hex / optional fields. Ethers serializers\n * accept hex strings for numeric fields. Normalize where helpful.\n */\nexport function normalizeTxForEmblem(tx: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...tx };\n\n if (out.value !== undefined) out.value = toHexIfBigInt(out.value);\n if (out.gas !== undefined) {\n out.gasLimit = toHexIfBigInt(out.gas);\n delete out.gas;\n }\n if (out.gasLimit !== undefined) out.gasLimit = toHexIfBigInt(out.gasLimit);\n if (out.gasPrice !== undefined) out.gasPrice = toHexIfBigInt(out.gasPrice);\n if (out.maxFeePerGas !== undefined) out.maxFeePerGas = toHexIfBigInt(out.maxFeePerGas);\n if (out.maxPriorityFeePerGas !== undefined)\n out.maxPriorityFeePerGas = toHexIfBigInt(out.maxPriorityFeePerGas);\n if (out.nonce !== undefined) out.nonce = toSafeNumber(out.nonce, 'nonce');\n if (out.chainId !== undefined) out.chainId = toSafeNumber(out.chainId, 'chainId');\n\n // Some backends only accept legacy fields; fold EIP-1559 into gasPrice and drop unsupported keys\n if (out.maxFeePerGas !== undefined || out.maxPriorityFeePerGas !== undefined) {\n if (out.gasPrice === undefined && out.maxFeePerGas !== undefined) {\n out.gasPrice = out.maxFeePerGas;\n }\n delete out.maxFeePerGas;\n delete out.maxPriorityFeePerGas;\n }\n\n // Remove fields commonly unsupported by legacy serializers\n delete out.type;\n delete out.accessList;\n delete out.account;\n delete out.chain;\n delete out.from;\n\n return out;\n}\n\nexport function isHexString(value: unknown): value is Hex {\n return typeof value === 'string' && /^0x[0-9a-fA-F]*$/.test(value);\n}\n\nexport function bytesToHex(bytes: ArrayLike<number>): Hex {\n let out = '0x';\n for (let i = 0; i < bytes.length; i++) {\n out += (bytes[i] as number).toString(16).padStart(2, '0');\n }\n return out as Hex;\n}\n","import type { SignerConfig, SignerVaultInfo, Hex } from '../types/signers';\nimport { emblemPost } from './http';\n\nexport async function fetchVaultInfo(config: SignerConfig): Promise<SignerVaultInfo> {\n // Note: The server only supports POST for /vault/info\n const data: Partial<{\n vaultId: string;\n address: string;\n evmAddress: Hex;\n created_by?: string;\n }> = await emblemPost('/vault/info', {}, config);\n\n // Validate required response data (vaultId + evmAddress are required for EVM)\n if (!data || !data.vaultId || !data.evmAddress) {\n throw new Error('Invalid vault info response: missing required fields');\n }\n\n if (!String(data.evmAddress).startsWith('0x')) {\n throw new Error('Invalid evmAddress format in response');\n }\n\n return {\n vaultId: data.vaultId,\n tokenId: data.vaultId,\n address: data.address || '', // Solana address may be absent; keep optional\n evmAddress: data.evmAddress as Hex,\n created_by: data.created_by,\n };\n}\n","import type { Hex, SignerConfig, SignerVaultInfo } from '../types/signers';\nimport { emblemPost } from './http';\nimport { bytesToHex, normalizeTxForEmblem } from './utils';\nimport { fetchVaultInfo } from './vault';\n\n// ethers v6 compatible interface (like solana pattern - no runtime dependency)\nexport interface EmblemEthersWallet {\n getAddress(): Promise<string>;\n signMessage(message: string | Uint8Array): Promise<string>;\n signTypedData(\n domain: unknown,\n types: Record<string, Array<{ name: string; type: string }>>,\n value: Record<string, unknown>\n ): Promise<string>;\n signTransaction(tx: unknown): Promise<string>;\n sendTransaction(tx: unknown): Promise<unknown>;\n connect(provider: unknown): EmblemEthersWallet;\n provider: unknown;\n // Additional methods\n initialize(): Promise<void>;\n getVaultId(): string;\n setChainId(chainId: number): void;\n getChainId(): number;\n signAndBroadcast(transaction: unknown, waitForReceipt?: boolean): Promise<string>;\n}\n\nexport async function toEthersWallet(\n config: SignerConfig,\n provider?: unknown | null,\n infoOverride?: SignerVaultInfo\n): Promise<EmblemEthersWallet> {\n // Dynamic import - only loads ethers when this function is called\n // String concatenation prevents bundlers from statically analyzing the import\n let ethers: typeof import('ethers');\n try {\n const moduleName = 'ethers';\n ethers = await import(/* @vite-ignore */ moduleName);\n } catch {\n throw new Error('ethers is required for toEthersWallet(). Install it with: npm install ethers');\n }\n\n const { AbstractSigner, resolveAddress } = ethers;\n type AbstractProvider = import('ethers').AbstractProvider;\n type TransactionRequest = import('ethers').TransactionRequest;\n type TransactionResponse = import('ethers').TransactionResponse;\n type TransactionLike = import('ethers').TransactionLike<string>;\n type TypedDataDomain = import('ethers').TypedDataDomain;\n type TypedDataField = import('ethers').TypedDataField;\n\n const info = infoOverride ?? (await fetchVaultInfo(config));\n\n // Class defined inside function after dynamic import\n class EmblemEthersWalletImpl extends AbstractSigner {\n private readonly _config: SignerConfig;\n private _address: Hex | null = null;\n private _vaultId: string | null = null;\n private _chainId = 1;\n private _initPromise?: Promise<void>;\n\n constructor(\n signerConfig: SignerConfig,\n signerProvider?: AbstractProvider | null,\n seed?: { address?: Hex; vaultId?: string; chainId?: number }\n ) {\n super(signerProvider ?? null);\n this._config = signerConfig;\n if (seed?.address) this._address = seed.address;\n if (seed?.vaultId) this._vaultId = seed.vaultId;\n if (seed?.chainId) this._chainId = seed.chainId;\n }\n\n async initialize(): Promise<void> {\n if (this._initPromise) return this._initPromise;\n\n this._initPromise = fetchVaultInfo(this._config)\n .then((vaultInfo) => {\n this._address = vaultInfo.evmAddress;\n this._vaultId = vaultInfo.vaultId;\n })\n .catch((err) => {\n this._initPromise = undefined;\n throw err;\n });\n\n return this._initPromise;\n }\n\n async getAddress(): Promise<string> {\n if (!this._address) await this.initialize();\n return this._address!;\n }\n\n getVaultId(): string {\n if (!this._vaultId) throw new Error('Wallet not initialized. Call initialize() first.');\n return this._vaultId;\n }\n\n setChainId(chainId: number): void {\n this._chainId = chainId;\n }\n\n getChainId(): number {\n return this._chainId;\n }\n\n connect(newProvider: AbstractProvider): EmblemEthersWalletImpl {\n if (!newProvider) throw new Error('Provider cannot be null');\n return new EmblemEthersWalletImpl(this._config, newProvider, {\n address: this._address ?? undefined,\n vaultId: this._vaultId ?? undefined,\n chainId: this._chainId,\n });\n }\n\n async signMessage(message: string | Uint8Array): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const payload = typeof message === 'string' ? message : bytesToHex(message);\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-eth-message',\n { vaultId: this._vaultId!, message: payload },\n this._config\n );\n return data.signature;\n }\n\n async signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const cleanTypes = { ...types };\n if (cleanTypes && (cleanTypes as Record<string, unknown>).EIP712Domain) {\n delete (cleanTypes as Record<string, unknown>).EIP712Domain;\n }\n const data = await emblemPost<{ signerAddress: string; signature: Hex }>(\n '/sign-typed-message',\n { vaultId: this._vaultId!, domain, types: cleanTypes, message: value },\n this._config\n );\n return data.signature;\n }\n\n async _signTypedData(\n domain: TypedDataDomain,\n types: Record<string, Array<TypedDataField>>,\n value: Record<string, unknown>\n ): Promise<string> {\n return this.signTypedData(domain, types, value);\n }\n\n async signTransaction(tx: TransactionRequest): Promise<string> {\n if (!this._vaultId) await this.initialize();\n const from = (tx as Record<string, unknown>).from as string | undefined;\n const addr = await this.getAddress();\n\n if (from && from.toLowerCase() !== addr.toLowerCase()) {\n throw new Error('transaction from does not match signer address');\n }\n\n const toSign = this.provider\n ? ({ ...await this.populateTransaction(tx) } as Record<string, unknown>)\n : ({ ...tx } as Record<string, unknown>);\n if (toSign.from) delete toSign.from;\n if (!('to' in toSign) || !toSign.to) {\n throw new Error(\"Transaction must have a 'to' address\");\n }\n if (toSign.nonce === undefined || toSign.nonce === null) {\n throw new Error('Transaction must have a nonce');\n }\n const normalized = normalizeTxForEmblem(toSign);\n const resp = await emblemPost<{ signedTransaction: Hex }>(\n '/sign-eth-tx',\n { vaultId: this._vaultId!, transaction: normalized, options: { chainId: this._chainId } },\n this._config\n );\n return resp.signedTransaction;\n }\n\n async sendTransaction(tx: TransactionRequest): Promise<TransactionResponse> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(tx);\n return await this.provider.broadcastTransaction(signed);\n }\n\n async populateTransaction(transaction: TransactionRequest): Promise<TransactionLike> {\n const tx = { ...transaction } as TransactionRequest;\n if (!this.provider) throw new Error('Provider required to populate transaction');\n const fromAddress = tx.from\n ? await resolveAddress(tx.from, this.provider)\n : await this.getAddress();\n\n let chainId: bigint;\n if (!tx.chainId) {\n const network = await this.provider.getNetwork();\n chainId = network.chainId;\n this._chainId = Number(network.chainId);\n } else {\n chainId = BigInt(tx.chainId);\n this._chainId = Number(tx.chainId);\n }\n\n const nonce =\n tx.nonce != null\n ? Number(tx.nonce)\n : await this.provider.getTransactionCount(fromAddress, 'pending');\n const toAddress = tx.to ? await resolveAddress(tx.to, this.provider) : null;\n const value = tx.value ? BigInt(tx.value.toString()) : 0n;\n\n let gasLimit: bigint;\n if (!tx.gasLimit) {\n try {\n gasLimit = await this.provider.estimateGas({ ...tx, from: fromAddress });\n } catch {\n gasLimit = 21000n;\n }\n } else {\n gasLimit = BigInt(tx.gasLimit.toString());\n }\n\n let gasPrice: bigint | null = null;\n if (!tx.gasPrice && tx.type !== 2) {\n const feeData = await this.provider.getFeeData();\n gasPrice = feeData.gasPrice ?? null;\n } else if (tx.gasPrice) {\n gasPrice = BigInt(tx.gasPrice.toString());\n }\n\n const populated: TransactionLike = {\n from: fromAddress,\n to: toAddress,\n value,\n nonce,\n gasLimit,\n data: tx.data as string | undefined,\n chainId,\n type: tx.type || undefined,\n };\n if (gasPrice !== null) populated.gasPrice = gasPrice;\n if (tx.maxFeePerGas) populated.maxFeePerGas = BigInt(tx.maxFeePerGas.toString());\n if (tx.maxPriorityFeePerGas)\n populated.maxPriorityFeePerGas = BigInt(tx.maxPriorityFeePerGas.toString());\n return populated;\n }\n\n async signAndBroadcast(\n transaction: TransactionRequest,\n waitForReceipt: boolean = false\n ): Promise<string> {\n if (!this.provider) throw new Error('Provider required to send transaction');\n const signed = await this.signTransaction(transaction);\n const resp = await this.provider.broadcastTransaction(signed);\n const hash = resp.hash as string;\n if (waitForReceipt) {\n await this.provider.waitForTransaction(hash);\n }\n return hash;\n }\n }\n\n return new EmblemEthersWalletImpl(config, provider as AbstractProvider | null, {\n address: info.evmAddress,\n vaultId: info.vaultId,\n });\n}\n"],"names":["async","emblemPost","path","body","config","baseUrl","authHeaders","getAuthHeaders","h","tok","jwt","getJwt","undefined","sdk","getSession","authToken","Authorization","apiKey","Error","resolveAuthHeaders","res","fetch","method","headers","JSON","stringify","_key","value","toString","ok","text","catch","status","errorMessage","substring","sanitizeErrorMessage","json","toSafeNumber","fieldName","num","Number","isSafeInteger","MAX_SAFE_INTEGER","toHexIfBigInt","v","fetchVaultInfo","data","vaultId","evmAddress","String","startsWith","tokenId","address","created_by","toEthersWallet","provider","infoOverride","ethers","moduleName","import","AbstractSigner","resolveAddress","info","EmblemEthersWalletImpl","constructor","signerConfig","signerProvider","seed","super","this","_address","_vaultId","_chainId","_config","chainId","initialize","_initPromise","then","vaultInfo","err","getAddress","getVaultId","setChainId","getChainId","connect","newProvider","signMessage","message","payload","bytes","out","i","length","padStart","bytesToHex","signature","signTypedData","domain","types","cleanTypes","EIP712Domain","_signTypedData","signTransaction","tx","from","addr","toLowerCase","toSign","populateTransaction","to","nonce","normalized","gas","gasLimit","gasPrice","maxFeePerGas","maxPriorityFeePerGas","type","accessList","account","chain","normalizeTxForEmblem","transaction","options","signedTransaction","sendTransaction","signed","broadcastTransaction","fromAddress","BigInt","network","getNetwork","getTransactionCount","toAddress","estimateGas","getFeeData","populated","signAndBroadcast","waitForReceipt","hash","waitForTransaction"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";function t(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach(function(r){if("default"!==r){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}}),e.default=t,Object.freeze(e)}function e(t,e){let r=`Emblem signer error ${t}`;return t>=500?r+=": Internal server error":401===t||403===t?r+=": Authentication failed":404===t?r+=": Resource not found":405===t?r+=": Method not allowed":e&&(r+=`: ${e.substring(0,200)}`),r}async function r(t){if("function"==typeof t.getAuthHeaders){const e=await t.getAuthHeaders();if(e&&"object"==typeof e)return e}const e=t.jwt??("function"==typeof t.getJwt?await t.getJwt():void 0)??t.sdk?.getSession()?.authToken??void 0;if(e)return{Authorization:`Bearer ${e}`};if(t.apiKey)return{"x-api-key":t.apiKey};throw new Error("No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey")}async function i(t,i,n){const a=n.baseUrl??"https://api.emblemvault.ai",s=await r(n),o=await fetch(`${a}${t}`,{method:"POST",headers:{"content-type":"application/json",...s},body:JSON.stringify(i,(t,e)=>"bigint"==typeof e?e.toString():e)});if(!o.ok){const t=await o.text().catch(()=>"");throw new Error(e(o.status,t))}return o.json()}function n(){return"undefined"!=typeof window&&"undefined"!=typeof document}function a(t){if(t){if(!t.startsWith("http://")&&!t.startsWith("https://"))throw new Error("baseUrl must be a valid HTTP(S) URL");!t.startsWith("http://")||t.includes("localhost")||t.includes("127.0.0.1")||console.warn("[Emblem Security Warning] baseUrl uses HTTP instead of HTTPS. This is insecure for production use.")}}function s(t,e){const r=Number(t);if(!Number.isSafeInteger(r))throw new Error(`${e} value ${t} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`);return r}function o(t){return"bigint"==typeof t?"0x"+t.toString(16):t}function d(t){const e={...t};return void 0!==e.value&&(e.value=o(e.value)),void 0!==e.gas&&(e.gasLimit=o(e.gas),delete e.gas),void 0!==e.gasLimit&&(e.gasLimit=o(e.gasLimit)),void 0!==e.gasPrice&&(e.gasPrice=o(e.gasPrice)),void 0!==e.maxFeePerGas&&(e.maxFeePerGas=o(e.maxFeePerGas)),void 0!==e.maxPriorityFeePerGas&&(e.maxPriorityFeePerGas=o(e.maxPriorityFeePerGas)),void 0!==e.nonce&&(e.nonce=s(e.nonce,"nonce")),void 0!==e.chainId&&(e.chainId=s(e.chainId,"chainId")),void 0===e.maxFeePerGas&&void 0===e.maxPriorityFeePerGas||(void 0===e.gasPrice&&void 0!==e.maxFeePerGas&&(e.gasPrice=e.maxFeePerGas),delete e.maxFeePerGas,delete e.maxPriorityFeePerGas),delete e.type,delete e.accessList,delete e.account,delete e.chain,delete e.from,e}function c(t){return"string"==typeof t&&/^0x[0-9a-fA-F]*$/.test(t)}function u(t){let e="0x";for(let r=0;r<t.length;r++)e+=t[r].toString(16).padStart(2,"0");return e}async function l(t){const e=await i("/vault/info",{},t);if(!e||!e.vaultId||!e.evmAddress)throw new Error("Invalid vault info response: missing required fields");if(!String(e.evmAddress).startsWith("0x"))throw new Error("Invalid evmAddress format in response");return{vaultId:e.vaultId,tokenId:e.vaultId,address:e.address||"",evmAddress:e.evmAddress,created_by:e.created_by}}Object.defineProperty(exports,"__esModule",{value:!0});class h{constructor(t,e){this.publicKey=e.address,this.config=t,this.vaultId=e.vaultId}async signMessage(t){const e="string"==typeof t?(new TextEncoder).encode(t):t,r=btoa(String.fromCharCode(...e)),n=await i("/sign-solana-message",{vaultId:this.vaultId,message:r},this.config);try{const t="undefined"!=typeof window?window:void 0;if(t?.bs58)return t.bs58.decode(n.signature);return Uint8Array.from(atob(n.signature),t=>t.charCodeAt(0))}catch(t){if(n.signature.startsWith("0x")){const t=n.signature.slice(2),e=new Uint8Array(t.length/2);for(let r=0;r<t.length;r+=2)e[r/2]=parseInt(t.substr(r,2),16);return e}throw new Error(`Unable to decode signature format: ${t}`)}}async signTransaction(t){const e=this.serializeTransaction(t),r=await i("/sign-solana-transaction",{vaultId:this.vaultId,transactionToSign:e,broadcast:!1,versionedTransaction:!0},this.config),n=r.serializedSignedTransaction||r.signedTransaction;if(!n)throw new Error("No signed transaction data received from server");return this.deserializeTransaction(n)}serializeTransaction(t){if(t&&"object"==typeof t){if(t.serialize){const e=t.serialize();return btoa(String.fromCharCode(...e))}if(t.instructions||t.recentBlockhash)throw new Error("Cannot serialize unsigned transaction objects. Please use VersionedTransaction.")}return t}deserializeTransaction(t){if("object"==typeof t&&t&&t.serializedSignedTransaction&&(t=t.serializedSignedTransaction),"string"==typeof t)try{const e=atob(t);return new Uint8Array(e.split("").map(t=>t.charCodeAt(0)))}catch(t){throw console.error("Failed to decode transaction:",t),new Error(`Unable to deserialize transaction response: ${t}`)}return t}getVaultId(){return this.vaultId}async signAllTransactions(t){const e=[];for(const r of t)e.push(await this.signTransaction(r));return e}canSign(t){return t===this.publicKey}async signAndBroadcast(t,e=!0){const r=this.serializeTransaction(t),n=await i("/sign-solana-transaction",{vaultId:this.vaultId,transactionToSign:r,broadcast:e,versionedTransaction:!0},this.config);if(e){if(!n.transactionSignature)throw new Error("No transaction signature received from broadcast");return n.transactionSignature}if(!n.serializedSignedTransaction)throw new Error("No signed transaction data received from server");return n.serializedSignedTransaction}}function g(t,e,r,i){if("a"===r&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?i:"a"===r?i.call(t):i?i.value:e.get(t)}function f(t,e,r,i,n){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?n.call(t,r):n?n.value=r:e.set(t,r),r}var w,v;"function"==typeof SuppressedError&&SuppressedError;class m{constructor(t,e,r){w.set(this,void 0),v.set(this,void 0),this.address=t,f(this,w,e,"f"),f(this,v,r,"f")}async signMessage(t){const e="string"==typeof t?t:u(t);return(await i("/sign-eth-message",{vaultId:g(this,w,"f"),message:e},g(this,v,"f"))).signature}async signTypedData(t,e,r){return(await i("/sign-typed-message",{vaultId:g(this,w,"f"),domain:t,types:e,message:r},g(this,v,"f"))).signature}async signTransaction(t){const e=d(t);return{rawTransaction:(await i("/sign-eth-tx",{vaultId:g(this,w,"f"),transaction:e},g(this,v,"f"))).signedTransaction}}}w=new WeakMap,v=new WeakMap,exports.EmblemSolanaSigner=h,exports.EmblemWeb3Adapter=m,exports.bytesToHex=u,exports.emblemGet=async function(t,i){const n=i.baseUrl??"https://api.emblemvault.ai",a=await r(i),s=await fetch(`${n}${t}`,{method:"GET",headers:a});if(!s.ok){const t=await s.text().catch(()=>"");throw new Error(e(s.status,t))}return s.json()},exports.emblemPost=i,exports.fetchVaultInfo=l,exports.isBrowserEnvironment=n,exports.isHexString=c,exports.isNodeEnvironment=function(){return"undefined"!=typeof process&&null!=process.versions&&null!=process.versions.node},exports.normalizeTxForEmblem=d,exports.toEthersWallet=async function(e,r,n){let a;try{a=await Promise.resolve().then(function(){return t(require("ethers"))})}catch{throw new Error("ethers is required for toEthersWallet(). Install it with: npm install ethers")}const{AbstractSigner:s,resolveAddress:o}=a,c=n??await l(e);class h extends s{constructor(t,e,r){super(e??null),this._address=null,this._vaultId=null,this._chainId=1,this._config=t,r?.address&&(this._address=r.address),r?.vaultId&&(this._vaultId=r.vaultId),r?.chainId&&(this._chainId=r.chainId)}async initialize(){return this._initPromise||(this._initPromise=l(this._config).then(t=>{this._address=t.evmAddress,this._vaultId=t.vaultId}).catch(t=>{throw this._initPromise=void 0,t})),this._initPromise}async getAddress(){return this._address||await this.initialize(),this._address}getVaultId(){if(!this._vaultId)throw new Error("Wallet not initialized. Call initialize() first.");return this._vaultId}setChainId(t){this._chainId=t}getChainId(){return this._chainId}connect(t){if(!t)throw new Error("Provider cannot be null");return new h(this._config,t,{address:this._address??void 0,vaultId:this._vaultId??void 0,chainId:this._chainId})}async signMessage(t){this._vaultId||await this.initialize();const e="string"==typeof t?t:u(t);return(await i("/sign-eth-message",{vaultId:this._vaultId,message:e},this._config)).signature}async signTypedData(t,e,r){this._vaultId||await this.initialize();const n={...e};n&&n.EIP712Domain&&delete n.EIP712Domain;return(await i("/sign-typed-message",{vaultId:this._vaultId,domain:t,types:n,message:r},this._config)).signature}async _signTypedData(t,e,r){return this.signTypedData(t,e,r)}async signTransaction(t){this._vaultId||await this.initialize();const e=t.from,r=await this.getAddress();if(e&&e.toLowerCase()!==r.toLowerCase())throw new Error("transaction from does not match signer address");const n=this.provider?{...await this.populateTransaction(t)}:{...t};if(n.from&&delete n.from,!("to"in n)||!n.to)throw new Error("Transaction must have a 'to' address");if(void 0===n.nonce||null===n.nonce)throw new Error("Transaction must have a nonce");const a=d(n);return(await i("/sign-eth-tx",{vaultId:this._vaultId,transaction:a,options:{chainId:this._chainId}},this._config)).signedTransaction}async sendTransaction(t){if(!this.provider)throw new Error("Provider required to send transaction");const e=await this.signTransaction(t);return await this.provider.broadcastTransaction(e)}async populateTransaction(t){const e={...t};if(!this.provider)throw new Error("Provider required to populate transaction");const r=e.from?await o(e.from,this.provider):await this.getAddress();let i;if(e.chainId)i=BigInt(e.chainId),this._chainId=Number(e.chainId);else{const t=await this.provider.getNetwork();i=t.chainId,this._chainId=Number(t.chainId)}const n=null!=e.nonce?Number(e.nonce):await this.provider.getTransactionCount(r,"pending"),a=e.to?await o(e.to,this.provider):null,s=e.value?BigInt(e.value.toString()):0n;let d;if(e.gasLimit)d=BigInt(e.gasLimit.toString());else try{d=await this.provider.estimateGas({...e,from:r})}catch{d=21000n}let c=null;if(e.gasPrice||2===e.type)e.gasPrice&&(c=BigInt(e.gasPrice.toString()));else{c=(await this.provider.getFeeData()).gasPrice??null}const u={from:r,to:a,value:s,nonce:n,gasLimit:d,data:e.data,chainId:i,type:e.type||void 0};return null!==c&&(u.gasPrice=c),e.maxFeePerGas&&(u.maxFeePerGas=BigInt(e.maxFeePerGas.toString())),e.maxPriorityFeePerGas&&(u.maxPriorityFeePerGas=BigInt(e.maxPriorityFeePerGas.toString())),u}async signAndBroadcast(t,e=!1){if(!this.provider)throw new Error("Provider required to send transaction");const r=await this.signTransaction(t),i=(await this.provider.broadcastTransaction(r)).hash;return e&&await this.provider.waitForTransaction(i),i}}return new h(e,r,{address:c.evmAddress,vaultId:c.vaultId})},exports.toHexIfBigInt=o,exports.toSafeNumber=s,exports.toSolanaKitSigner=async function(t,e){const r=e??await l(t);return new h(t,r)},exports.toSolanaWeb3Signer=async function(t,e){const r=e??await l(t);return new h(t,r)},exports.toViemAccount=async function(e,r){const n=r??await l(e),{evmAddress:a,vaultId:s}=n,{toAccount:o}=await Promise.resolve().then(function(){return t(require("viem/accounts"))});return o({address:a,async signMessage({message:t}){let r,n=!1;if("string"==typeof t)r=t,n=!1;else if(t&&void 0!==t.raw){const e=t.raw;r="string"==typeof e?e:u(e),n=!0}else if(t instanceof Uint8Array)r=u(t),n=!1;else{if(!c(t))throw new Error(`Unsupported message type: ${typeof t}. Expected string, Uint8Array, or hex string.`);r=t,n=!1}return(await i("/sign-eth-message",{vaultId:s,message:r,raw:n},e)).signature},async signTypedData(t){const{domain:r,types:n,message:a}=t;return(await i("/sign-typed-message",{vaultId:s,domain:r,types:n,message:a},e)).signature},async signTransaction(t,r){const n=d(t);return(await i("/sign-eth-tx",{vaultId:s,transaction:n},e)).signedTransaction}})},exports.toWeb3Adapter=async function(t,e){const r=e??await l(t);return new m(r.evmAddress,r.vaultId,t)},exports.validateBaseUrl=a,exports.validateEthereumAddress=function(t){if(!t||"string"!=typeof t)throw new Error("Address is required");if(!t.startsWith("0x"))throw new Error("Address must start with 0x");if(!/^0x[0-9a-fA-F]{40}$/.test(t))throw new Error("Invalid Ethereum address format")},exports.validateSignerConfig=function(t){const e=!!t.jwt,r="function"==typeof t.getJwt,i="function"==typeof t.getAuthHeaders;if(!e&&!r&&!i)throw new Error("Authentication required: provide jwt, getJwt(), or getAuthHeaders()");t.baseUrl&&a(t.baseUrl),t.debugSecurity&&console.log("[Emblem Security Debug]",{environment:n()?"browser":"node",hasBaseUrl:!!t.baseUrl,timestamp:(new Date).toISOString()})},exports.validateVaultId=function(t){if(!t||"string"!=typeof t)throw new Error("vaultId is required");if(""===t.trim())throw new Error("vaultId cannot be empty")};
1
+ "use strict";function t(t){if(t&&t.__esModule)return t;var e=Object.create(null);return t&&Object.keys(t).forEach(function(r){if("default"!==r){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}}),e.default=t,Object.freeze(e)}function e(t,e){let r=`Emblem signer error ${t}`;return t>=500?r+=": Internal server error":401===t||403===t?r+=": Authentication failed":404===t?r+=": Resource not found":405===t?r+=": Method not allowed":e&&(r+=`: ${e.substring(0,200)}`),r}async function r(t){if("function"==typeof t.getAuthHeaders){const e=await t.getAuthHeaders();if(e&&"object"==typeof e)return e}const e=t.jwt??("function"==typeof t.getJwt?await t.getJwt():void 0)??t.sdk?.getSession()?.authToken??void 0;if(e)return{Authorization:`Bearer ${e}`};if(t.apiKey)return{"x-api-key":t.apiKey};throw new Error("No authentication available: provide jwt, getJwt(), getAuthHeaders(), sdk, or apiKey")}async function i(t,i,n){const a=n.baseUrl??"https://api.emblemvault.ai",s=await r(n),o=await fetch(`${a}${t}`,{method:"POST",headers:{"content-type":"application/json",...s},body:JSON.stringify(i,(t,e)=>"bigint"==typeof e?e.toString():e)});if(!o.ok){const t=await o.text().catch(()=>"");throw new Error(e(o.status,t))}return o.json()}function n(){return"undefined"!=typeof window&&"undefined"!=typeof document}function a(t){if(t){if(!t.startsWith("http://")&&!t.startsWith("https://"))throw new Error("baseUrl must be a valid HTTP(S) URL");!t.startsWith("http://")||t.includes("localhost")||t.includes("127.0.0.1")||console.warn("[Emblem Security Warning] baseUrl uses HTTP instead of HTTPS. This is insecure for production use.")}}function s(t,e){const r=Number(t);if(!Number.isSafeInteger(r))throw new Error(`${e} value ${t} exceeds safe integer range (max: ${Number.MAX_SAFE_INTEGER})`);return r}function o(t){return"bigint"==typeof t?"0x"+t.toString(16):t}function d(t){const e={...t};return void 0!==e.value&&(e.value=o(e.value)),void 0!==e.gas&&(e.gasLimit=o(e.gas),delete e.gas),void 0!==e.gasLimit&&(e.gasLimit=o(e.gasLimit)),void 0!==e.gasPrice&&(e.gasPrice=o(e.gasPrice)),void 0!==e.maxFeePerGas&&(e.maxFeePerGas=o(e.maxFeePerGas)),void 0!==e.maxPriorityFeePerGas&&(e.maxPriorityFeePerGas=o(e.maxPriorityFeePerGas)),void 0!==e.nonce&&(e.nonce=s(e.nonce,"nonce")),void 0!==e.chainId&&(e.chainId=s(e.chainId,"chainId")),void 0===e.maxFeePerGas&&void 0===e.maxPriorityFeePerGas||(void 0===e.gasPrice&&void 0!==e.maxFeePerGas&&(e.gasPrice=e.maxFeePerGas),delete e.maxFeePerGas,delete e.maxPriorityFeePerGas),delete e.type,delete e.accessList,delete e.account,delete e.chain,delete e.from,e}function c(t){return"string"==typeof t&&/^0x[0-9a-fA-F]*$/.test(t)}function u(t){let e="0x";for(let r=0;r<t.length;r++)e+=t[r].toString(16).padStart(2,"0");return e}async function l(t){const e=await i("/vault/info",{},t);if(!e||!e.vaultId||!e.evmAddress)throw new Error("Invalid vault info response: missing required fields");if(!String(e.evmAddress).startsWith("0x"))throw new Error("Invalid evmAddress format in response");return{vaultId:e.vaultId,tokenId:e.vaultId,address:e.address||"",evmAddress:e.evmAddress,created_by:e.created_by}}Object.defineProperty(exports,"__esModule",{value:!0});class h{constructor(t,e){this.publicKey=e.address,this.config=t,this.vaultId=e.vaultId}async signMessage(t){const e="string"==typeof t?(new TextEncoder).encode(t):t,r=btoa(String.fromCharCode(...e)),n=await i("/sign-solana-message",{vaultId:this.vaultId,message:r},this.config);try{const t="undefined"!=typeof window?window:void 0;if(t?.bs58)return t.bs58.decode(n.signature);return Uint8Array.from(atob(n.signature),t=>t.charCodeAt(0))}catch(t){if(n.signature.startsWith("0x")){const t=n.signature.slice(2),e=new Uint8Array(t.length/2);for(let r=0;r<t.length;r+=2)e[r/2]=parseInt(t.substr(r,2),16);return e}throw new Error(`Unable to decode signature format: ${t}`)}}async signTransaction(t){const e=this.serializeTransaction(t),r=await i("/sign-solana-transaction",{vaultId:this.vaultId,transactionToSign:e,broadcast:!1,versionedTransaction:!0},this.config),n=r.serializedSignedTransaction||r.signedTransaction;if(!n)throw new Error("No signed transaction data received from server");return this.deserializeTransaction(n)}serializeTransaction(t){if(t&&"object"==typeof t){if(t.serialize){const e=t.serialize();return btoa(String.fromCharCode(...e))}if(t.instructions||t.recentBlockhash)throw new Error("Cannot serialize unsigned transaction objects. Please use VersionedTransaction.")}return t}deserializeTransaction(t){if("object"==typeof t&&t&&t.serializedSignedTransaction&&(t=t.serializedSignedTransaction),"string"==typeof t)try{const e=atob(t);return new Uint8Array(e.split("").map(t=>t.charCodeAt(0)))}catch(t){throw console.error("Failed to decode transaction:",t),new Error(`Unable to deserialize transaction response: ${t}`)}return t}getVaultId(){return this.vaultId}async signAllTransactions(t){const e=[];for(const r of t)e.push(await this.signTransaction(r));return e}canSign(t){return t===this.publicKey}async signAndBroadcast(t,e=!0){const r=this.serializeTransaction(t),n=await i("/sign-solana-transaction",{vaultId:this.vaultId,transactionToSign:r,broadcast:e,versionedTransaction:!0},this.config);if(e){if(!n.transactionSignature)throw new Error("No transaction signature received from broadcast");return n.transactionSignature}if(!n.serializedSignedTransaction)throw new Error("No signed transaction data received from server");return n.serializedSignedTransaction}}function g(t,e,r,i){if("a"===r&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?i:"a"===r?i.call(t):i?i.value:e.get(t)}function f(t,e,r,i,n){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!n)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?n.call(t,r):n?n.value=r:e.set(t,r),r}var w,v;"function"==typeof SuppressedError&&SuppressedError;class m{constructor(t,e,r){w.set(this,void 0),v.set(this,void 0),this.address=t,f(this,w,e,"f"),f(this,v,r,"f")}async signMessage(t){const e="string"==typeof t?t:u(t);return(await i("/sign-eth-message",{vaultId:g(this,w,"f"),message:e},g(this,v,"f"))).signature}async signTypedData(t,e,r){return(await i("/sign-typed-message",{vaultId:g(this,w,"f"),domain:t,types:e,message:r},g(this,v,"f"))).signature}async signTransaction(t){const e=d(t);return{rawTransaction:(await i("/sign-eth-tx",{vaultId:g(this,w,"f"),transaction:e},g(this,v,"f"))).signedTransaction}}}w=new WeakMap,v=new WeakMap,exports.EmblemSolanaSigner=h,exports.EmblemWeb3Adapter=m,exports.bytesToHex=u,exports.emblemGet=async function(t,i){const n=i.baseUrl??"https://api.emblemvault.ai",a=await r(i),s=await fetch(`${n}${t}`,{method:"GET",headers:a});if(!s.ok){const t=await s.text().catch(()=>"");throw new Error(e(s.status,t))}return s.json()},exports.emblemPost=i,exports.fetchVaultInfo=l,exports.isBrowserEnvironment=n,exports.isHexString=c,exports.isNodeEnvironment=function(){return"undefined"!=typeof process&&null!=process.versions&&null!=process.versions.node},exports.normalizeTxForEmblem=d,exports.toEthersWallet=async function(e,r,n){let a;try{const e="ethers";a=await(s=e,Promise.resolve().then(function(){return t(require(s))}))}catch{throw new Error("ethers is required for toEthersWallet(). Install it with: npm install ethers")}var s;const{AbstractSigner:o,resolveAddress:c}=a,h=n??await l(e);class g extends o{constructor(t,e,r){super(e??null),this._address=null,this._vaultId=null,this._chainId=1,this._config=t,r?.address&&(this._address=r.address),r?.vaultId&&(this._vaultId=r.vaultId),r?.chainId&&(this._chainId=r.chainId)}async initialize(){return this._initPromise||(this._initPromise=l(this._config).then(t=>{this._address=t.evmAddress,this._vaultId=t.vaultId}).catch(t=>{throw this._initPromise=void 0,t})),this._initPromise}async getAddress(){return this._address||await this.initialize(),this._address}getVaultId(){if(!this._vaultId)throw new Error("Wallet not initialized. Call initialize() first.");return this._vaultId}setChainId(t){this._chainId=t}getChainId(){return this._chainId}connect(t){if(!t)throw new Error("Provider cannot be null");return new g(this._config,t,{address:this._address??void 0,vaultId:this._vaultId??void 0,chainId:this._chainId})}async signMessage(t){this._vaultId||await this.initialize();const e="string"==typeof t?t:u(t);return(await i("/sign-eth-message",{vaultId:this._vaultId,message:e},this._config)).signature}async signTypedData(t,e,r){this._vaultId||await this.initialize();const n={...e};n&&n.EIP712Domain&&delete n.EIP712Domain;return(await i("/sign-typed-message",{vaultId:this._vaultId,domain:t,types:n,message:r},this._config)).signature}async _signTypedData(t,e,r){return this.signTypedData(t,e,r)}async signTransaction(t){this._vaultId||await this.initialize();const e=t.from,r=await this.getAddress();if(e&&e.toLowerCase()!==r.toLowerCase())throw new Error("transaction from does not match signer address");const n=this.provider?{...await this.populateTransaction(t)}:{...t};if(n.from&&delete n.from,!("to"in n)||!n.to)throw new Error("Transaction must have a 'to' address");if(void 0===n.nonce||null===n.nonce)throw new Error("Transaction must have a nonce");const a=d(n);return(await i("/sign-eth-tx",{vaultId:this._vaultId,transaction:a,options:{chainId:this._chainId}},this._config)).signedTransaction}async sendTransaction(t){if(!this.provider)throw new Error("Provider required to send transaction");const e=await this.signTransaction(t);return await this.provider.broadcastTransaction(e)}async populateTransaction(t){const e={...t};if(!this.provider)throw new Error("Provider required to populate transaction");const r=e.from?await c(e.from,this.provider):await this.getAddress();let i;if(e.chainId)i=BigInt(e.chainId),this._chainId=Number(e.chainId);else{const t=await this.provider.getNetwork();i=t.chainId,this._chainId=Number(t.chainId)}const n=null!=e.nonce?Number(e.nonce):await this.provider.getTransactionCount(r,"pending"),a=e.to?await c(e.to,this.provider):null,s=e.value?BigInt(e.value.toString()):0n;let o;if(e.gasLimit)o=BigInt(e.gasLimit.toString());else try{o=await this.provider.estimateGas({...e,from:r})}catch{o=21000n}let d=null;if(e.gasPrice||2===e.type)e.gasPrice&&(d=BigInt(e.gasPrice.toString()));else{d=(await this.provider.getFeeData()).gasPrice??null}const u={from:r,to:a,value:s,nonce:n,gasLimit:o,data:e.data,chainId:i,type:e.type||void 0};return null!==d&&(u.gasPrice=d),e.maxFeePerGas&&(u.maxFeePerGas=BigInt(e.maxFeePerGas.toString())),e.maxPriorityFeePerGas&&(u.maxPriorityFeePerGas=BigInt(e.maxPriorityFeePerGas.toString())),u}async signAndBroadcast(t,e=!1){if(!this.provider)throw new Error("Provider required to send transaction");const r=await this.signTransaction(t),i=(await this.provider.broadcastTransaction(r)).hash;return e&&await this.provider.waitForTransaction(i),i}}return new g(e,r,{address:h.evmAddress,vaultId:h.vaultId})},exports.toHexIfBigInt=o,exports.toSafeNumber=s,exports.toSolanaKitSigner=async function(t,e){const r=e??await l(t);return new h(t,r)},exports.toSolanaWeb3Signer=async function(t,e){const r=e??await l(t);return new h(t,r)},exports.toViemAccount=async function(e,r){const n=r??await l(e),{evmAddress:a,vaultId:s}=n,{toAccount:o}=await(h="viem/accounts",Promise.resolve().then(function(){return t(require(h))}));var h;return o({address:a,async signMessage({message:t}){let r,n=!1;if("string"==typeof t)r=t,n=!1;else if(t&&void 0!==t.raw){const e=t.raw;r="string"==typeof e?e:u(e),n=!0}else if(t instanceof Uint8Array)r=u(t),n=!1;else{if(!c(t))throw new Error(`Unsupported message type: ${typeof t}. Expected string, Uint8Array, or hex string.`);r=t,n=!1}return(await i("/sign-eth-message",{vaultId:s,message:r,raw:n},e)).signature},async signTypedData(t){const{domain:r,types:n,message:a}=t;return(await i("/sign-typed-message",{vaultId:s,domain:r,types:n,message:a},e)).signature},async signTransaction(t,r){const n=d(t);return(await i("/sign-eth-tx",{vaultId:s,transaction:n},e)).signedTransaction}})},exports.toWeb3Adapter=async function(t,e){const r=e??await l(t);return new m(r.evmAddress,r.vaultId,t)},exports.validateBaseUrl=a,exports.validateEthereumAddress=function(t){if(!t||"string"!=typeof t)throw new Error("Address is required");if(!t.startsWith("0x"))throw new Error("Address must start with 0x");if(!/^0x[0-9a-fA-F]{40}$/.test(t))throw new Error("Invalid Ethereum address format")},exports.validateSignerConfig=function(t){const e=!!t.jwt,r="function"==typeof t.getJwt,i="function"==typeof t.getAuthHeaders;if(!e&&!r&&!i)throw new Error("Authentication required: provide jwt, getJwt(), or getAuthHeaders()");t.baseUrl&&a(t.baseUrl),t.debugSecurity&&console.log("[Emblem Security Debug]",{environment:n()?"browser":"node",hasBaseUrl:!!t.baseUrl,timestamp:(new Date).toISOString()})},exports.validateVaultId=function(t){if(!t||"string"!=typeof t)throw new Error("vaultId is required");if(""===t.trim())throw new Error("vaultId cannot be empty")};
2
2
  //# sourceMappingURL=index.js.map