diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index f923d7433..0e580abe0 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -54,9 +54,15 @@ jobs: run: | if [ ! -d ".git" ]; then git clone https://github.com/${{ github.repository }}.git . + else + # Self-hosted runners keep the workspace between runs; ensure clean checkout + git reset --hard HEAD + git clean -fdx fi git fetch origin ${{ github.sha }} --depth=1 --tags - git checkout ${{ github.sha }} + git checkout -f ${{ github.sha }} + git reset --hard HEAD + git clean -fdx - name: Determine channel id: channel diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 643fbdf2a..c9d6c0c04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,9 +18,15 @@ jobs: run: | if [ ! -d ".git" ]; then git clone --depth=1 https://github.com/${{ github.repository }}.git . + else + # Self-hosted runners keep the workspace between runs; ensure clean checkout + git reset --hard HEAD + git clean -fdx fi git fetch origin ${{ github.event.pull_request.head.sha || github.sha }} --depth=1 - git checkout ${{ github.event.pull_request.head.sha || github.sha }} + git checkout -f ${{ github.event.pull_request.head.sha || github.sha }} + git reset --hard HEAD + git clean -fdx - name: Detect changes id: changes diff --git a/miniapps/forge/src/hooks/useForge.test.ts b/miniapps/forge/src/hooks/useForge.test.ts index add886698..364e8841f 100644 --- a/miniapps/forge/src/hooks/useForge.test.ts +++ b/miniapps/forge/src/hooks/useForge.test.ts @@ -19,10 +19,10 @@ const mockForgeParams: ForgeParams = { externalAsset: 'ETH', depositAddress: '0xdeposit123', amount: '1.5', - externalAccount: { address: '0xexternal123', chain: 'eth' }, + externalAccount: { address: '0xexternal123', chain: 'eth', publicKey: '0x' }, internalChain: 'bfmeta', internalAsset: 'BFM', - internalAccount: { address: 'bfmeta123', chain: 'bfmeta' }, + internalAccount: { address: 'bfmeta123', chain: 'bfmeta', publicKey: '0x' }, } describe('useForge', () => { diff --git a/packages/bio-sdk/dist/index.cjs.map b/packages/bio-sdk/dist/index.cjs.map index 6b72557ba..e6b4df822 100644 --- a/packages/bio-sdk/dist/index.cjs.map +++ b/packages/bio-sdk/dist/index.cjs.map @@ -1 +1 @@ -{"version":3,"file":"index.cjs","sources":["../src/types.ts","../src/events.ts","../src/provider.ts","../src/index.ts"],"sourcesContent":["/**\n * Bio SDK Types\n * EIP-1193 style provider interface for Bio ecosystem\n */\n\n/** Account information */\nexport interface BioAccount {\n address: string\n chain: string\n name?: string\n}\n\n/** Transfer parameters */\nexport interface TransferParams {\n from: string\n to: string\n amount: string\n chain: string\n asset?: string\n}\n\n/** Unsigned transaction payload (chain-specific) */\nexport interface BioUnsignedTransaction {\n chainId: string\n data: unknown\n}\n\n/** Signed transaction payload (chain-specific) */\nexport interface BioSignedTransaction {\n chainId: string\n data: unknown\n signature: string\n}\n\n/** Provider request arguments */\nexport interface RequestArguments {\n method: string\n params?: unknown[]\n}\n\n/** Provider RPC error */\nexport interface ProviderRpcError extends Error {\n code: number\n data?: unknown\n}\n\n/** Event handler type */\nexport type EventHandler = (...args: T[]) => void\n\n/**\n * Bio Provider Interface (EIP-1193 style)\n */\nexport interface BioProvider {\n /** Make a request to the provider */\n request(args: RequestArguments): Promise\n\n /** Subscribe to an event */\n on(event: string, handler: EventHandler): void\n\n /** Unsubscribe from an event */\n off(event: string, handler: EventHandler): void\n\n /** Check if connected */\n isConnected(): boolean\n}\n\n/**\n * Bio method definitions\n */\nexport interface BioMethods {\n /** Request wallet accounts (shows connection UI) */\n bio_requestAccounts: () => Promise\n\n /** Get connected accounts (no UI) */\n bio_accounts: () => Promise\n\n /** Select an account (shows account picker UI) */\n bio_selectAccount: (opts?: { chain?: string }) => Promise\n\n /** Pick another wallet address (shows wallet picker UI) */\n bio_pickWallet: (opts?: { chain?: string; exclude?: string }) => Promise\n\n /** Sign a message */\n bio_signMessage: (params: { message: string; address: string }) => Promise\n\n /** Sign typed data */\n bio_signTypedData: (params: { data: object; address: string }) => Promise\n\n /** Create an unsigned transaction (no signature, no broadcast) */\n bio_createTransaction: (params: TransferParams) => Promise\n\n /** Sign an unsigned transaction (requires user confirmation) */\n bio_signTransaction: (params: { from: string; chain: string; unsignedTx: BioUnsignedTransaction }) => Promise\n\n /** Send a transaction */\n bio_sendTransaction: (params: TransferParams) => Promise<{ txHash: string }>\n\n /** Get current chain ID */\n bio_chainId: () => Promise\n\n /** Get balance */\n bio_getBalance: (params: { address: string; chain: string }) => Promise\n\n /** Close splash screen (indicates app is ready) */\n bio_closeSplashScreen: () => Promise\n}\n\n/**\n * Bio event definitions\n */\nexport interface BioEvents {\n /** Emitted when accounts change */\n accountsChanged: (accounts: BioAccount[]) => void\n\n /** Emitted when chain changes */\n chainChanged: (chainId: string) => void\n\n /** Emitted when connected */\n connect: (info: { chainId: string }) => void\n\n /** Emitted when disconnected */\n disconnect: (error: { code: number; message: string }) => void\n}\n\n/** Method names */\nexport type BioMethodName = keyof BioMethods\n\n/** Event names */\nexport type BioEventName = keyof BioEvents\n\n/** RPC error codes */\nexport const BioErrorCodes = {\n USER_REJECTED: 4001,\n UNAUTHORIZED: 4100,\n UNSUPPORTED_METHOD: 4200,\n DISCONNECTED: 4900,\n CHAIN_DISCONNECTED: 4901,\n INTERNAL_ERROR: -32603,\n INVALID_PARAMS: -32602,\n METHOD_NOT_FOUND: -32601,\n} as const\n\n/** Create a provider RPC error */\nexport function createProviderError(code: number, message: string, data?: unknown): ProviderRpcError {\n const error = new Error(message) as ProviderRpcError\n error.code = code\n error.data = data\n return error\n}\n","/**\n * Event emitter for Bio SDK\n */\n\nimport type { EventHandler } from './types'\n\nexport class EventEmitter {\n private handlers = new Map>()\n\n on(event: string, handler: EventHandler): void {\n let handlers = this.handlers.get(event)\n if (!handlers) {\n handlers = new Set()\n this.handlers.set(event, handlers)\n }\n handlers.add(handler)\n }\n\n off(event: string, handler: EventHandler): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n emit(event: string, ...args: unknown[]): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(...args)\n } catch (error) {\n console.error(`[BioSDK] Error in event handler for \"${event}\":`, error)\n }\n })\n }\n }\n\n removeAllListeners(event?: string): void {\n if (event) {\n this.handlers.delete(event)\n } else {\n this.handlers.clear()\n }\n }\n}\n","/**\n * Bio Provider Implementation\n * Communicates with KeyApp host via postMessage\n */\n\nimport type { BioProvider, RequestArguments, EventHandler } from './types'\nimport { BioErrorCodes, createProviderError } from './types'\nimport { EventEmitter } from './events'\n\n/** Message sent to host */\ninterface RequestMessage {\n type: 'bio_request'\n id: string\n method: string\n params?: unknown[]\n}\n\n/** Response from host */\ninterface ResponseMessage {\n type: 'bio_response'\n id: string\n success: boolean\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\n/** Event from host */\ninterface EventMessage {\n type: 'bio_event'\n event: string\n args: unknown[]\n}\n\ntype HostMessage = ResponseMessage | EventMessage\n\nexport class BioProviderImpl implements BioProvider {\n private events = new EventEmitter()\n private pendingRequests = new Map void\n reject: (error: Error) => void\n }>()\n private requestIdCounter = 0\n private connected = false\n private readonly targetOrigin: string\n\n constructor(targetOrigin = '*') {\n this.targetOrigin = targetOrigin\n this.setupMessageListener()\n this.connect()\n }\n\n private setupMessageListener(): void {\n window.addEventListener('message', this.handleMessage.bind(this))\n }\n\n private handleMessage(event: MessageEvent): void {\n const data = event.data as HostMessage\n if (!data || typeof data !== 'object') return\n\n if (data.type === 'bio_response') {\n this.handleResponse(data)\n } else if (data.type === 'bio_event') {\n this.handleEvent(data)\n }\n }\n\n private handleResponse(message: ResponseMessage): void {\n const pending = this.pendingRequests.get(message.id)\n if (!pending) return\n\n this.pendingRequests.delete(message.id)\n\n if (message.success) {\n pending.resolve(message.result)\n } else {\n const error = message.error ?? { code: BioErrorCodes.INTERNAL_ERROR, message: 'Unknown error' }\n pending.reject(createProviderError(error.code, error.message, error.data))\n }\n }\n\n private handleEvent(message: EventMessage): void {\n this.events.emit(message.event, ...message.args)\n\n // Handle built-in events\n if (message.event === 'connect') {\n this.connected = true\n } else if (message.event === 'disconnect') {\n this.connected = false\n }\n }\n\n private connect(): void {\n // Send handshake to host\n this.postMessage({\n type: 'bio_request',\n id: this.generateId(),\n method: 'bio_connect',\n params: [],\n })\n }\n\n private generateId(): string {\n return `bio_${Date.now()}_${++this.requestIdCounter}`\n }\n\n private postMessage(message: RequestMessage): void {\n if (window.parent === window) {\n console.warn('[BioSDK] Not running in iframe, cannot communicate with host')\n return\n }\n window.parent.postMessage(message, this.targetOrigin)\n }\n\n async request(args: RequestArguments): Promise {\n const id = this.generateId()\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n })\n\n this.postMessage({\n type: 'bio_request',\n id,\n method: args.method,\n params: args.params,\n })\n\n // Timeout after 5 minutes (for user interactions)\n setTimeout(() => {\n if (this.pendingRequests.has(id)) {\n this.pendingRequests.delete(id)\n reject(createProviderError(BioErrorCodes.INTERNAL_ERROR, 'Request timeout'))\n }\n }, 5 * 60 * 1000)\n })\n }\n\n on(event: string, handler: EventHandler): void {\n this.events.on(event, handler)\n }\n\n off(event: string, handler: EventHandler): void {\n this.events.off(event, handler)\n }\n\n isConnected(): boolean {\n return this.connected\n }\n}\n","/**\n * Bio SDK - Client SDK for Bio Ecosystem MiniApps\n *\n * Injects `window.bio` provider similar to `window.ethereum` in Web3 DApps.\n *\n * @example\n * ```typescript\n * import '@biochain/bio-sdk'\n *\n * // Now window.bio is available\n * const accounts = await window.bio.request({ method: 'bio_requestAccounts' })\n * ```\n */\n\nimport { BioProviderImpl } from './provider'\nimport type { BioProvider } from './types'\n\n// Re-export types\nexport * from './types'\nexport { EventEmitter } from './events'\nexport { BioProviderImpl } from './provider'\n\n// Extend Window interface\ndeclare global {\n interface Window {\n bio?: BioProvider\n }\n}\n\n/**\n * Initialize and inject the Bio provider into window.bio\n */\nexport function initBioProvider(targetOrigin = '*'): BioProvider {\n if (typeof window === 'undefined') {\n throw new Error('[BioSDK] Cannot initialize: window is not defined')\n }\n\n if (window.bio) {\n console.warn('[BioSDK] Provider already exists, returning existing instance')\n return window.bio\n }\n\n const provider = new BioProviderImpl(targetOrigin)\n window.bio = provider\n\n console.log('[BioSDK] Provider initialized')\n return provider\n}\n\n// Auto-initialize if running in browser\nif (typeof window !== 'undefined') {\n // Use a slight delay to ensure DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => initBioProvider())\n } else {\n initBioProvider()\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.cjs","sources":["../src/types.ts","../src/events.ts","../src/provider.ts","../src/index.ts"],"sourcesContent":["/**\n * Bio SDK Types\n * EIP-1193 style provider interface for Bio ecosystem\n */\n\n/** Account information */\nexport interface BioAccount {\n address: string\n chain: string\n name?: string\n /** Public key (hex encoded) */\n publicKey: string\n}\n\n/** Transfer parameters */\nexport interface TransferParams {\n from: string\n to: string\n amount: string\n chain: string\n asset?: string\n}\n\n/** Unsigned transaction payload (chain-specific) */\nexport interface BioUnsignedTransaction {\n chainId: string\n data: unknown\n}\n\n/** Signed transaction payload (chain-specific) */\nexport interface BioSignedTransaction {\n chainId: string\n data: unknown\n signature: string\n}\n\n/** Provider request arguments */\nexport interface RequestArguments {\n method: string\n params?: unknown[]\n}\n\n/** Provider RPC error */\nexport interface ProviderRpcError extends Error {\n code: number\n data?: unknown\n}\n\n/** Event handler type */\nexport type EventHandler = (...args: T[]) => void\n\n/**\n * Bio Provider Interface (EIP-1193 style)\n */\nexport interface BioProvider {\n /** Make a request to the provider */\n request(args: RequestArguments): Promise\n\n /** Subscribe to an event */\n on(event: string, handler: EventHandler): void\n\n /** Unsubscribe from an event */\n off(event: string, handler: EventHandler): void\n\n /** Check if connected */\n isConnected(): boolean\n}\n\n/**\n * Bio method definitions\n */\nexport interface BioMethods {\n /** Request wallet accounts (shows connection UI) */\n bio_requestAccounts: () => Promise\n\n /** Get connected accounts (no UI) */\n bio_accounts: () => Promise\n\n /** Select an account (shows account picker UI) */\n bio_selectAccount: (opts?: { chain?: string }) => Promise\n\n /** Pick another wallet address (shows wallet picker UI) */\n bio_pickWallet: (opts?: { chain?: string; exclude?: string }) => Promise\n\n /** Sign a message, returns signature and public key (hex) */\n bio_signMessage: (params: { message: string; address: string }) => Promise<{ signature: string; publicKey: string }>\n\n /** Sign typed data, returns signature and public key (hex) */\n bio_signTypedData: (params: { data: object; address: string }) => Promise<{ signature: string; publicKey: string }>\n\n /** Create an unsigned transaction (no signature, no broadcast) */\n bio_createTransaction: (params: TransferParams) => Promise\n\n /** Sign an unsigned transaction (requires user confirmation) */\n bio_signTransaction: (params: { from: string; chain: string; unsignedTx: BioUnsignedTransaction }) => Promise\n\n /** Send a transaction */\n bio_sendTransaction: (params: TransferParams) => Promise<{ txHash: string }>\n\n /** Get current chain ID */\n bio_chainId: () => Promise\n\n /** Get balance */\n bio_getBalance: (params: { address: string; chain: string }) => Promise\n\n /** Close splash screen (indicates app is ready) */\n bio_closeSplashScreen: () => Promise\n}\n\n/**\n * Bio event definitions\n */\nexport interface BioEvents {\n /** Emitted when accounts change */\n accountsChanged: (accounts: BioAccount[]) => void\n\n /** Emitted when chain changes */\n chainChanged: (chainId: string) => void\n\n /** Emitted when connected */\n connect: (info: { chainId: string }) => void\n\n /** Emitted when disconnected */\n disconnect: (error: { code: number; message: string }) => void\n}\n\n/** Method names */\nexport type BioMethodName = keyof BioMethods\n\n/** Event names */\nexport type BioEventName = keyof BioEvents\n\n/** RPC error codes */\nexport const BioErrorCodes = {\n USER_REJECTED: 4001,\n UNAUTHORIZED: 4100,\n UNSUPPORTED_METHOD: 4200,\n DISCONNECTED: 4900,\n CHAIN_DISCONNECTED: 4901,\n INTERNAL_ERROR: -32603,\n INVALID_PARAMS: -32602,\n METHOD_NOT_FOUND: -32601,\n} as const\n\n/** Create a provider RPC error */\nexport function createProviderError(code: number, message: string, data?: unknown): ProviderRpcError {\n const error = new Error(message) as ProviderRpcError\n error.code = code\n error.data = data\n return error\n}\n","/**\n * Event emitter for Bio SDK\n */\n\nimport type { EventHandler } from './types'\n\nexport class EventEmitter {\n private handlers = new Map>()\n\n on(event: string, handler: EventHandler): void {\n let handlers = this.handlers.get(event)\n if (!handlers) {\n handlers = new Set()\n this.handlers.set(event, handlers)\n }\n handlers.add(handler)\n }\n\n off(event: string, handler: EventHandler): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n emit(event: string, ...args: unknown[]): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(...args)\n } catch (error) {\n console.error(`[BioSDK] Error in event handler for \"${event}\":`, error)\n }\n })\n }\n }\n\n removeAllListeners(event?: string): void {\n if (event) {\n this.handlers.delete(event)\n } else {\n this.handlers.clear()\n }\n }\n}\n","/**\n * Bio Provider Implementation\n * Communicates with KeyApp host via postMessage\n */\n\nimport type { BioProvider, RequestArguments, EventHandler } from './types'\nimport { BioErrorCodes, createProviderError } from './types'\nimport { EventEmitter } from './events'\n\n/** Message sent to host */\ninterface RequestMessage {\n type: 'bio_request'\n id: string\n method: string\n params?: unknown[]\n}\n\n/** Response from host */\ninterface ResponseMessage {\n type: 'bio_response'\n id: string\n success: boolean\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\n/** Event from host */\ninterface EventMessage {\n type: 'bio_event'\n event: string\n args: unknown[]\n}\n\ntype HostMessage = ResponseMessage | EventMessage\n\nexport class BioProviderImpl implements BioProvider {\n private events = new EventEmitter()\n private pendingRequests = new Map void\n reject: (error: Error) => void\n }>()\n private requestIdCounter = 0\n private connected = false\n private readonly targetOrigin: string\n\n constructor(targetOrigin = '*') {\n this.targetOrigin = targetOrigin\n this.setupMessageListener()\n this.connect()\n }\n\n private setupMessageListener(): void {\n window.addEventListener('message', this.handleMessage.bind(this))\n }\n\n private handleMessage(event: MessageEvent): void {\n const data = event.data as HostMessage\n if (!data || typeof data !== 'object') return\n\n if (data.type === 'bio_response') {\n this.handleResponse(data)\n } else if (data.type === 'bio_event') {\n this.handleEvent(data)\n }\n }\n\n private handleResponse(message: ResponseMessage): void {\n const pending = this.pendingRequests.get(message.id)\n if (!pending) return\n\n this.pendingRequests.delete(message.id)\n\n if (message.success) {\n pending.resolve(message.result)\n } else {\n const error = message.error ?? { code: BioErrorCodes.INTERNAL_ERROR, message: 'Unknown error' }\n pending.reject(createProviderError(error.code, error.message, error.data))\n }\n }\n\n private handleEvent(message: EventMessage): void {\n this.events.emit(message.event, ...message.args)\n\n // Handle built-in events\n if (message.event === 'connect') {\n this.connected = true\n } else if (message.event === 'disconnect') {\n this.connected = false\n }\n }\n\n private connect(): void {\n // Send handshake to host\n this.postMessage({\n type: 'bio_request',\n id: this.generateId(),\n method: 'bio_connect',\n params: [],\n })\n }\n\n private generateId(): string {\n return `bio_${Date.now()}_${++this.requestIdCounter}`\n }\n\n private postMessage(message: RequestMessage): void {\n if (window.parent === window) {\n console.warn('[BioSDK] Not running in iframe, cannot communicate with host')\n return\n }\n window.parent.postMessage(message, this.targetOrigin)\n }\n\n async request(args: RequestArguments): Promise {\n const id = this.generateId()\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n })\n\n this.postMessage({\n type: 'bio_request',\n id,\n method: args.method,\n params: args.params,\n })\n\n // Timeout after 5 minutes (for user interactions)\n setTimeout(() => {\n if (this.pendingRequests.has(id)) {\n this.pendingRequests.delete(id)\n reject(createProviderError(BioErrorCodes.INTERNAL_ERROR, 'Request timeout'))\n }\n }, 5 * 60 * 1000)\n })\n }\n\n on(event: string, handler: EventHandler): void {\n this.events.on(event, handler)\n }\n\n off(event: string, handler: EventHandler): void {\n this.events.off(event, handler)\n }\n\n isConnected(): boolean {\n return this.connected\n }\n}\n","/**\n * Bio SDK - Client SDK for Bio Ecosystem MiniApps\n *\n * Injects `window.bio` provider similar to `window.ethereum` in Web3 DApps.\n *\n * @example\n * ```typescript\n * import '@biochain/bio-sdk'\n *\n * // Now window.bio is available\n * const accounts = await window.bio.request({ method: 'bio_requestAccounts' })\n * ```\n */\n\nimport { BioProviderImpl } from './provider'\nimport type { BioProvider } from './types'\n\n// Re-export types\nexport * from './types'\nexport { EventEmitter } from './events'\nexport { BioProviderImpl } from './provider'\n\n// Extend Window interface\ndeclare global {\n interface Window {\n bio?: BioProvider\n }\n}\n\n/**\n * Initialize and inject the Bio provider into window.bio\n */\nexport function initBioProvider(targetOrigin = '*'): BioProvider {\n if (typeof window === 'undefined') {\n throw new Error('[BioSDK] Cannot initialize: window is not defined')\n }\n\n if (window.bio) {\n console.warn('[BioSDK] Provider already exists, returning existing instance')\n return window.bio\n }\n\n const provider = new BioProviderImpl(targetOrigin)\n window.bio = provider\n\n console.log('[BioSDK] Provider initialized')\n return provider\n}\n\n// Auto-initialize if running in browser\nif (typeof window !== 'undefined') {\n // Use a slight delay to ensure DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => initBioProvider())\n } else {\n initBioProvider()\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/bio-sdk/dist/index.d.ts b/packages/bio-sdk/dist/index.d.ts index a220e2acf..5b18d899f 100644 --- a/packages/bio-sdk/dist/index.d.ts +++ b/packages/bio-sdk/dist/index.d.ts @@ -7,6 +7,8 @@ export declare interface BioAccount { address: string; chain: string; name?: string; + /** Public key (hex encoded) */ + publicKey: string; } /** RPC error codes */ @@ -63,16 +65,22 @@ export declare interface BioMethods { chain?: string; exclude?: string; }) => Promise; - /** Sign a message */ + /** Sign a message, returns signature and public key (hex) */ bio_signMessage: (params: { message: string; address: string; - }) => Promise; - /** Sign typed data */ + }) => Promise<{ + signature: string; + publicKey: string; + }>; + /** Sign typed data, returns signature and public key (hex) */ bio_signTypedData: (params: { data: object; address: string; - }) => Promise; + }) => Promise<{ + signature: string; + publicKey: string; + }>; /** Create an unsigned transaction (no signature, no broadcast) */ bio_createTransaction: (params: TransferParams) => Promise; /** Sign an unsigned transaction (requires user confirmation) */ diff --git a/packages/bio-sdk/dist/index.js.map b/packages/bio-sdk/dist/index.js.map index ca3bf139c..0eb660931 100644 --- a/packages/bio-sdk/dist/index.js.map +++ b/packages/bio-sdk/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../src/types.ts","../src/events.ts","../src/provider.ts","../src/index.ts"],"sourcesContent":["/**\n * Bio SDK Types\n * EIP-1193 style provider interface for Bio ecosystem\n */\n\n/** Account information */\nexport interface BioAccount {\n address: string\n chain: string\n name?: string\n}\n\n/** Transfer parameters */\nexport interface TransferParams {\n from: string\n to: string\n amount: string\n chain: string\n asset?: string\n}\n\n/** Unsigned transaction payload (chain-specific) */\nexport interface BioUnsignedTransaction {\n chainId: string\n data: unknown\n}\n\n/** Signed transaction payload (chain-specific) */\nexport interface BioSignedTransaction {\n chainId: string\n data: unknown\n signature: string\n}\n\n/** Provider request arguments */\nexport interface RequestArguments {\n method: string\n params?: unknown[]\n}\n\n/** Provider RPC error */\nexport interface ProviderRpcError extends Error {\n code: number\n data?: unknown\n}\n\n/** Event handler type */\nexport type EventHandler = (...args: T[]) => void\n\n/**\n * Bio Provider Interface (EIP-1193 style)\n */\nexport interface BioProvider {\n /** Make a request to the provider */\n request(args: RequestArguments): Promise\n\n /** Subscribe to an event */\n on(event: string, handler: EventHandler): void\n\n /** Unsubscribe from an event */\n off(event: string, handler: EventHandler): void\n\n /** Check if connected */\n isConnected(): boolean\n}\n\n/**\n * Bio method definitions\n */\nexport interface BioMethods {\n /** Request wallet accounts (shows connection UI) */\n bio_requestAccounts: () => Promise\n\n /** Get connected accounts (no UI) */\n bio_accounts: () => Promise\n\n /** Select an account (shows account picker UI) */\n bio_selectAccount: (opts?: { chain?: string }) => Promise\n\n /** Pick another wallet address (shows wallet picker UI) */\n bio_pickWallet: (opts?: { chain?: string; exclude?: string }) => Promise\n\n /** Sign a message */\n bio_signMessage: (params: { message: string; address: string }) => Promise\n\n /** Sign typed data */\n bio_signTypedData: (params: { data: object; address: string }) => Promise\n\n /** Create an unsigned transaction (no signature, no broadcast) */\n bio_createTransaction: (params: TransferParams) => Promise\n\n /** Sign an unsigned transaction (requires user confirmation) */\n bio_signTransaction: (params: { from: string; chain: string; unsignedTx: BioUnsignedTransaction }) => Promise\n\n /** Send a transaction */\n bio_sendTransaction: (params: TransferParams) => Promise<{ txHash: string }>\n\n /** Get current chain ID */\n bio_chainId: () => Promise\n\n /** Get balance */\n bio_getBalance: (params: { address: string; chain: string }) => Promise\n\n /** Close splash screen (indicates app is ready) */\n bio_closeSplashScreen: () => Promise\n}\n\n/**\n * Bio event definitions\n */\nexport interface BioEvents {\n /** Emitted when accounts change */\n accountsChanged: (accounts: BioAccount[]) => void\n\n /** Emitted when chain changes */\n chainChanged: (chainId: string) => void\n\n /** Emitted when connected */\n connect: (info: { chainId: string }) => void\n\n /** Emitted when disconnected */\n disconnect: (error: { code: number; message: string }) => void\n}\n\n/** Method names */\nexport type BioMethodName = keyof BioMethods\n\n/** Event names */\nexport type BioEventName = keyof BioEvents\n\n/** RPC error codes */\nexport const BioErrorCodes = {\n USER_REJECTED: 4001,\n UNAUTHORIZED: 4100,\n UNSUPPORTED_METHOD: 4200,\n DISCONNECTED: 4900,\n CHAIN_DISCONNECTED: 4901,\n INTERNAL_ERROR: -32603,\n INVALID_PARAMS: -32602,\n METHOD_NOT_FOUND: -32601,\n} as const\n\n/** Create a provider RPC error */\nexport function createProviderError(code: number, message: string, data?: unknown): ProviderRpcError {\n const error = new Error(message) as ProviderRpcError\n error.code = code\n error.data = data\n return error\n}\n","/**\n * Event emitter for Bio SDK\n */\n\nimport type { EventHandler } from './types'\n\nexport class EventEmitter {\n private handlers = new Map>()\n\n on(event: string, handler: EventHandler): void {\n let handlers = this.handlers.get(event)\n if (!handlers) {\n handlers = new Set()\n this.handlers.set(event, handlers)\n }\n handlers.add(handler)\n }\n\n off(event: string, handler: EventHandler): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n emit(event: string, ...args: unknown[]): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(...args)\n } catch (error) {\n console.error(`[BioSDK] Error in event handler for \"${event}\":`, error)\n }\n })\n }\n }\n\n removeAllListeners(event?: string): void {\n if (event) {\n this.handlers.delete(event)\n } else {\n this.handlers.clear()\n }\n }\n}\n","/**\n * Bio Provider Implementation\n * Communicates with KeyApp host via postMessage\n */\n\nimport type { BioProvider, RequestArguments, EventHandler } from './types'\nimport { BioErrorCodes, createProviderError } from './types'\nimport { EventEmitter } from './events'\n\n/** Message sent to host */\ninterface RequestMessage {\n type: 'bio_request'\n id: string\n method: string\n params?: unknown[]\n}\n\n/** Response from host */\ninterface ResponseMessage {\n type: 'bio_response'\n id: string\n success: boolean\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\n/** Event from host */\ninterface EventMessage {\n type: 'bio_event'\n event: string\n args: unknown[]\n}\n\ntype HostMessage = ResponseMessage | EventMessage\n\nexport class BioProviderImpl implements BioProvider {\n private events = new EventEmitter()\n private pendingRequests = new Map void\n reject: (error: Error) => void\n }>()\n private requestIdCounter = 0\n private connected = false\n private readonly targetOrigin: string\n\n constructor(targetOrigin = '*') {\n this.targetOrigin = targetOrigin\n this.setupMessageListener()\n this.connect()\n }\n\n private setupMessageListener(): void {\n window.addEventListener('message', this.handleMessage.bind(this))\n }\n\n private handleMessage(event: MessageEvent): void {\n const data = event.data as HostMessage\n if (!data || typeof data !== 'object') return\n\n if (data.type === 'bio_response') {\n this.handleResponse(data)\n } else if (data.type === 'bio_event') {\n this.handleEvent(data)\n }\n }\n\n private handleResponse(message: ResponseMessage): void {\n const pending = this.pendingRequests.get(message.id)\n if (!pending) return\n\n this.pendingRequests.delete(message.id)\n\n if (message.success) {\n pending.resolve(message.result)\n } else {\n const error = message.error ?? { code: BioErrorCodes.INTERNAL_ERROR, message: 'Unknown error' }\n pending.reject(createProviderError(error.code, error.message, error.data))\n }\n }\n\n private handleEvent(message: EventMessage): void {\n this.events.emit(message.event, ...message.args)\n\n // Handle built-in events\n if (message.event === 'connect') {\n this.connected = true\n } else if (message.event === 'disconnect') {\n this.connected = false\n }\n }\n\n private connect(): void {\n // Send handshake to host\n this.postMessage({\n type: 'bio_request',\n id: this.generateId(),\n method: 'bio_connect',\n params: [],\n })\n }\n\n private generateId(): string {\n return `bio_${Date.now()}_${++this.requestIdCounter}`\n }\n\n private postMessage(message: RequestMessage): void {\n if (window.parent === window) {\n console.warn('[BioSDK] Not running in iframe, cannot communicate with host')\n return\n }\n window.parent.postMessage(message, this.targetOrigin)\n }\n\n async request(args: RequestArguments): Promise {\n const id = this.generateId()\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n })\n\n this.postMessage({\n type: 'bio_request',\n id,\n method: args.method,\n params: args.params,\n })\n\n // Timeout after 5 minutes (for user interactions)\n setTimeout(() => {\n if (this.pendingRequests.has(id)) {\n this.pendingRequests.delete(id)\n reject(createProviderError(BioErrorCodes.INTERNAL_ERROR, 'Request timeout'))\n }\n }, 5 * 60 * 1000)\n })\n }\n\n on(event: string, handler: EventHandler): void {\n this.events.on(event, handler)\n }\n\n off(event: string, handler: EventHandler): void {\n this.events.off(event, handler)\n }\n\n isConnected(): boolean {\n return this.connected\n }\n}\n","/**\n * Bio SDK - Client SDK for Bio Ecosystem MiniApps\n *\n * Injects `window.bio` provider similar to `window.ethereum` in Web3 DApps.\n *\n * @example\n * ```typescript\n * import '@biochain/bio-sdk'\n *\n * // Now window.bio is available\n * const accounts = await window.bio.request({ method: 'bio_requestAccounts' })\n * ```\n */\n\nimport { BioProviderImpl } from './provider'\nimport type { BioProvider } from './types'\n\n// Re-export types\nexport * from './types'\nexport { EventEmitter } from './events'\nexport { BioProviderImpl } from './provider'\n\n// Extend Window interface\ndeclare global {\n interface Window {\n bio?: BioProvider\n }\n}\n\n/**\n * Initialize and inject the Bio provider into window.bio\n */\nexport function initBioProvider(targetOrigin = '*'): BioProvider {\n if (typeof window === 'undefined') {\n throw new Error('[BioSDK] Cannot initialize: window is not defined')\n }\n\n if (window.bio) {\n console.warn('[BioSDK] Provider already exists, returning existing instance')\n return window.bio\n }\n\n const provider = new BioProviderImpl(targetOrigin)\n window.bio = provider\n\n console.log('[BioSDK] Provider initialized')\n return provider\n}\n\n// Auto-initialize if running in browser\nif (typeof window !== 'undefined') {\n // Use a slight delay to ensure DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => initBioProvider())\n } else {\n initBioProvider()\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["../src/types.ts","../src/events.ts","../src/provider.ts","../src/index.ts"],"sourcesContent":["/**\n * Bio SDK Types\n * EIP-1193 style provider interface for Bio ecosystem\n */\n\n/** Account information */\nexport interface BioAccount {\n address: string\n chain: string\n name?: string\n /** Public key (hex encoded) */\n publicKey: string\n}\n\n/** Transfer parameters */\nexport interface TransferParams {\n from: string\n to: string\n amount: string\n chain: string\n asset?: string\n}\n\n/** Unsigned transaction payload (chain-specific) */\nexport interface BioUnsignedTransaction {\n chainId: string\n data: unknown\n}\n\n/** Signed transaction payload (chain-specific) */\nexport interface BioSignedTransaction {\n chainId: string\n data: unknown\n signature: string\n}\n\n/** Provider request arguments */\nexport interface RequestArguments {\n method: string\n params?: unknown[]\n}\n\n/** Provider RPC error */\nexport interface ProviderRpcError extends Error {\n code: number\n data?: unknown\n}\n\n/** Event handler type */\nexport type EventHandler = (...args: T[]) => void\n\n/**\n * Bio Provider Interface (EIP-1193 style)\n */\nexport interface BioProvider {\n /** Make a request to the provider */\n request(args: RequestArguments): Promise\n\n /** Subscribe to an event */\n on(event: string, handler: EventHandler): void\n\n /** Unsubscribe from an event */\n off(event: string, handler: EventHandler): void\n\n /** Check if connected */\n isConnected(): boolean\n}\n\n/**\n * Bio method definitions\n */\nexport interface BioMethods {\n /** Request wallet accounts (shows connection UI) */\n bio_requestAccounts: () => Promise\n\n /** Get connected accounts (no UI) */\n bio_accounts: () => Promise\n\n /** Select an account (shows account picker UI) */\n bio_selectAccount: (opts?: { chain?: string }) => Promise\n\n /** Pick another wallet address (shows wallet picker UI) */\n bio_pickWallet: (opts?: { chain?: string; exclude?: string }) => Promise\n\n /** Sign a message, returns signature and public key (hex) */\n bio_signMessage: (params: { message: string; address: string }) => Promise<{ signature: string; publicKey: string }>\n\n /** Sign typed data, returns signature and public key (hex) */\n bio_signTypedData: (params: { data: object; address: string }) => Promise<{ signature: string; publicKey: string }>\n\n /** Create an unsigned transaction (no signature, no broadcast) */\n bio_createTransaction: (params: TransferParams) => Promise\n\n /** Sign an unsigned transaction (requires user confirmation) */\n bio_signTransaction: (params: { from: string; chain: string; unsignedTx: BioUnsignedTransaction }) => Promise\n\n /** Send a transaction */\n bio_sendTransaction: (params: TransferParams) => Promise<{ txHash: string }>\n\n /** Get current chain ID */\n bio_chainId: () => Promise\n\n /** Get balance */\n bio_getBalance: (params: { address: string; chain: string }) => Promise\n\n /** Close splash screen (indicates app is ready) */\n bio_closeSplashScreen: () => Promise\n}\n\n/**\n * Bio event definitions\n */\nexport interface BioEvents {\n /** Emitted when accounts change */\n accountsChanged: (accounts: BioAccount[]) => void\n\n /** Emitted when chain changes */\n chainChanged: (chainId: string) => void\n\n /** Emitted when connected */\n connect: (info: { chainId: string }) => void\n\n /** Emitted when disconnected */\n disconnect: (error: { code: number; message: string }) => void\n}\n\n/** Method names */\nexport type BioMethodName = keyof BioMethods\n\n/** Event names */\nexport type BioEventName = keyof BioEvents\n\n/** RPC error codes */\nexport const BioErrorCodes = {\n USER_REJECTED: 4001,\n UNAUTHORIZED: 4100,\n UNSUPPORTED_METHOD: 4200,\n DISCONNECTED: 4900,\n CHAIN_DISCONNECTED: 4901,\n INTERNAL_ERROR: -32603,\n INVALID_PARAMS: -32602,\n METHOD_NOT_FOUND: -32601,\n} as const\n\n/** Create a provider RPC error */\nexport function createProviderError(code: number, message: string, data?: unknown): ProviderRpcError {\n const error = new Error(message) as ProviderRpcError\n error.code = code\n error.data = data\n return error\n}\n","/**\n * Event emitter for Bio SDK\n */\n\nimport type { EventHandler } from './types'\n\nexport class EventEmitter {\n private handlers = new Map>()\n\n on(event: string, handler: EventHandler): void {\n let handlers = this.handlers.get(event)\n if (!handlers) {\n handlers = new Set()\n this.handlers.set(event, handlers)\n }\n handlers.add(handler)\n }\n\n off(event: string, handler: EventHandler): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n emit(event: string, ...args: unknown[]): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(...args)\n } catch (error) {\n console.error(`[BioSDK] Error in event handler for \"${event}\":`, error)\n }\n })\n }\n }\n\n removeAllListeners(event?: string): void {\n if (event) {\n this.handlers.delete(event)\n } else {\n this.handlers.clear()\n }\n }\n}\n","/**\n * Bio Provider Implementation\n * Communicates with KeyApp host via postMessage\n */\n\nimport type { BioProvider, RequestArguments, EventHandler } from './types'\nimport { BioErrorCodes, createProviderError } from './types'\nimport { EventEmitter } from './events'\n\n/** Message sent to host */\ninterface RequestMessage {\n type: 'bio_request'\n id: string\n method: string\n params?: unknown[]\n}\n\n/** Response from host */\ninterface ResponseMessage {\n type: 'bio_response'\n id: string\n success: boolean\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\n/** Event from host */\ninterface EventMessage {\n type: 'bio_event'\n event: string\n args: unknown[]\n}\n\ntype HostMessage = ResponseMessage | EventMessage\n\nexport class BioProviderImpl implements BioProvider {\n private events = new EventEmitter()\n private pendingRequests = new Map void\n reject: (error: Error) => void\n }>()\n private requestIdCounter = 0\n private connected = false\n private readonly targetOrigin: string\n\n constructor(targetOrigin = '*') {\n this.targetOrigin = targetOrigin\n this.setupMessageListener()\n this.connect()\n }\n\n private setupMessageListener(): void {\n window.addEventListener('message', this.handleMessage.bind(this))\n }\n\n private handleMessage(event: MessageEvent): void {\n const data = event.data as HostMessage\n if (!data || typeof data !== 'object') return\n\n if (data.type === 'bio_response') {\n this.handleResponse(data)\n } else if (data.type === 'bio_event') {\n this.handleEvent(data)\n }\n }\n\n private handleResponse(message: ResponseMessage): void {\n const pending = this.pendingRequests.get(message.id)\n if (!pending) return\n\n this.pendingRequests.delete(message.id)\n\n if (message.success) {\n pending.resolve(message.result)\n } else {\n const error = message.error ?? { code: BioErrorCodes.INTERNAL_ERROR, message: 'Unknown error' }\n pending.reject(createProviderError(error.code, error.message, error.data))\n }\n }\n\n private handleEvent(message: EventMessage): void {\n this.events.emit(message.event, ...message.args)\n\n // Handle built-in events\n if (message.event === 'connect') {\n this.connected = true\n } else if (message.event === 'disconnect') {\n this.connected = false\n }\n }\n\n private connect(): void {\n // Send handshake to host\n this.postMessage({\n type: 'bio_request',\n id: this.generateId(),\n method: 'bio_connect',\n params: [],\n })\n }\n\n private generateId(): string {\n return `bio_${Date.now()}_${++this.requestIdCounter}`\n }\n\n private postMessage(message: RequestMessage): void {\n if (window.parent === window) {\n console.warn('[BioSDK] Not running in iframe, cannot communicate with host')\n return\n }\n window.parent.postMessage(message, this.targetOrigin)\n }\n\n async request(args: RequestArguments): Promise {\n const id = this.generateId()\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n })\n\n this.postMessage({\n type: 'bio_request',\n id,\n method: args.method,\n params: args.params,\n })\n\n // Timeout after 5 minutes (for user interactions)\n setTimeout(() => {\n if (this.pendingRequests.has(id)) {\n this.pendingRequests.delete(id)\n reject(createProviderError(BioErrorCodes.INTERNAL_ERROR, 'Request timeout'))\n }\n }, 5 * 60 * 1000)\n })\n }\n\n on(event: string, handler: EventHandler): void {\n this.events.on(event, handler)\n }\n\n off(event: string, handler: EventHandler): void {\n this.events.off(event, handler)\n }\n\n isConnected(): boolean {\n return this.connected\n }\n}\n","/**\n * Bio SDK - Client SDK for Bio Ecosystem MiniApps\n *\n * Injects `window.bio` provider similar to `window.ethereum` in Web3 DApps.\n *\n * @example\n * ```typescript\n * import '@biochain/bio-sdk'\n *\n * // Now window.bio is available\n * const accounts = await window.bio.request({ method: 'bio_requestAccounts' })\n * ```\n */\n\nimport { BioProviderImpl } from './provider'\nimport type { BioProvider } from './types'\n\n// Re-export types\nexport * from './types'\nexport { EventEmitter } from './events'\nexport { BioProviderImpl } from './provider'\n\n// Extend Window interface\ndeclare global {\n interface Window {\n bio?: BioProvider\n }\n}\n\n/**\n * Initialize and inject the Bio provider into window.bio\n */\nexport function initBioProvider(targetOrigin = '*'): BioProvider {\n if (typeof window === 'undefined') {\n throw new Error('[BioSDK] Cannot initialize: window is not defined')\n }\n\n if (window.bio) {\n console.warn('[BioSDK] Provider already exists, returning existing instance')\n return window.bio\n }\n\n const provider = new BioProviderImpl(targetOrigin)\n window.bio = provider\n\n console.log('[BioSDK] Provider initialized')\n return provider\n}\n\n// Auto-initialize if running in browser\nif (typeof window !== 'undefined') {\n // Use a slight delay to ensure DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => initBioProvider())\n } else {\n initBioProvider()\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/bio-sdk/dist/index.umd.js.map b/packages/bio-sdk/dist/index.umd.js.map index 11d87f830..19761307f 100644 --- a/packages/bio-sdk/dist/index.umd.js.map +++ b/packages/bio-sdk/dist/index.umd.js.map @@ -1 +1 @@ -{"version":3,"file":"index.umd.js","sources":["../src/types.ts","../src/events.ts","../src/provider.ts","../src/index.ts"],"sourcesContent":["/**\n * Bio SDK Types\n * EIP-1193 style provider interface for Bio ecosystem\n */\n\n/** Account information */\nexport interface BioAccount {\n address: string\n chain: string\n name?: string\n}\n\n/** Transfer parameters */\nexport interface TransferParams {\n from: string\n to: string\n amount: string\n chain: string\n asset?: string\n}\n\n/** Unsigned transaction payload (chain-specific) */\nexport interface BioUnsignedTransaction {\n chainId: string\n data: unknown\n}\n\n/** Signed transaction payload (chain-specific) */\nexport interface BioSignedTransaction {\n chainId: string\n data: unknown\n signature: string\n}\n\n/** Provider request arguments */\nexport interface RequestArguments {\n method: string\n params?: unknown[]\n}\n\n/** Provider RPC error */\nexport interface ProviderRpcError extends Error {\n code: number\n data?: unknown\n}\n\n/** Event handler type */\nexport type EventHandler = (...args: T[]) => void\n\n/**\n * Bio Provider Interface (EIP-1193 style)\n */\nexport interface BioProvider {\n /** Make a request to the provider */\n request(args: RequestArguments): Promise\n\n /** Subscribe to an event */\n on(event: string, handler: EventHandler): void\n\n /** Unsubscribe from an event */\n off(event: string, handler: EventHandler): void\n\n /** Check if connected */\n isConnected(): boolean\n}\n\n/**\n * Bio method definitions\n */\nexport interface BioMethods {\n /** Request wallet accounts (shows connection UI) */\n bio_requestAccounts: () => Promise\n\n /** Get connected accounts (no UI) */\n bio_accounts: () => Promise\n\n /** Select an account (shows account picker UI) */\n bio_selectAccount: (opts?: { chain?: string }) => Promise\n\n /** Pick another wallet address (shows wallet picker UI) */\n bio_pickWallet: (opts?: { chain?: string; exclude?: string }) => Promise\n\n /** Sign a message */\n bio_signMessage: (params: { message: string; address: string }) => Promise\n\n /** Sign typed data */\n bio_signTypedData: (params: { data: object; address: string }) => Promise\n\n /** Create an unsigned transaction (no signature, no broadcast) */\n bio_createTransaction: (params: TransferParams) => Promise\n\n /** Sign an unsigned transaction (requires user confirmation) */\n bio_signTransaction: (params: { from: string; chain: string; unsignedTx: BioUnsignedTransaction }) => Promise\n\n /** Send a transaction */\n bio_sendTransaction: (params: TransferParams) => Promise<{ txHash: string }>\n\n /** Get current chain ID */\n bio_chainId: () => Promise\n\n /** Get balance */\n bio_getBalance: (params: { address: string; chain: string }) => Promise\n\n /** Close splash screen (indicates app is ready) */\n bio_closeSplashScreen: () => Promise\n}\n\n/**\n * Bio event definitions\n */\nexport interface BioEvents {\n /** Emitted when accounts change */\n accountsChanged: (accounts: BioAccount[]) => void\n\n /** Emitted when chain changes */\n chainChanged: (chainId: string) => void\n\n /** Emitted when connected */\n connect: (info: { chainId: string }) => void\n\n /** Emitted when disconnected */\n disconnect: (error: { code: number; message: string }) => void\n}\n\n/** Method names */\nexport type BioMethodName = keyof BioMethods\n\n/** Event names */\nexport type BioEventName = keyof BioEvents\n\n/** RPC error codes */\nexport const BioErrorCodes = {\n USER_REJECTED: 4001,\n UNAUTHORIZED: 4100,\n UNSUPPORTED_METHOD: 4200,\n DISCONNECTED: 4900,\n CHAIN_DISCONNECTED: 4901,\n INTERNAL_ERROR: -32603,\n INVALID_PARAMS: -32602,\n METHOD_NOT_FOUND: -32601,\n} as const\n\n/** Create a provider RPC error */\nexport function createProviderError(code: number, message: string, data?: unknown): ProviderRpcError {\n const error = new Error(message) as ProviderRpcError\n error.code = code\n error.data = data\n return error\n}\n","/**\n * Event emitter for Bio SDK\n */\n\nimport type { EventHandler } from './types'\n\nexport class EventEmitter {\n private handlers = new Map>()\n\n on(event: string, handler: EventHandler): void {\n let handlers = this.handlers.get(event)\n if (!handlers) {\n handlers = new Set()\n this.handlers.set(event, handlers)\n }\n handlers.add(handler)\n }\n\n off(event: string, handler: EventHandler): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n emit(event: string, ...args: unknown[]): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(...args)\n } catch (error) {\n console.error(`[BioSDK] Error in event handler for \"${event}\":`, error)\n }\n })\n }\n }\n\n removeAllListeners(event?: string): void {\n if (event) {\n this.handlers.delete(event)\n } else {\n this.handlers.clear()\n }\n }\n}\n","/**\n * Bio Provider Implementation\n * Communicates with KeyApp host via postMessage\n */\n\nimport type { BioProvider, RequestArguments, EventHandler } from './types'\nimport { BioErrorCodes, createProviderError } from './types'\nimport { EventEmitter } from './events'\n\n/** Message sent to host */\ninterface RequestMessage {\n type: 'bio_request'\n id: string\n method: string\n params?: unknown[]\n}\n\n/** Response from host */\ninterface ResponseMessage {\n type: 'bio_response'\n id: string\n success: boolean\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\n/** Event from host */\ninterface EventMessage {\n type: 'bio_event'\n event: string\n args: unknown[]\n}\n\ntype HostMessage = ResponseMessage | EventMessage\n\nexport class BioProviderImpl implements BioProvider {\n private events = new EventEmitter()\n private pendingRequests = new Map void\n reject: (error: Error) => void\n }>()\n private requestIdCounter = 0\n private connected = false\n private readonly targetOrigin: string\n\n constructor(targetOrigin = '*') {\n this.targetOrigin = targetOrigin\n this.setupMessageListener()\n this.connect()\n }\n\n private setupMessageListener(): void {\n window.addEventListener('message', this.handleMessage.bind(this))\n }\n\n private handleMessage(event: MessageEvent): void {\n const data = event.data as HostMessage\n if (!data || typeof data !== 'object') return\n\n if (data.type === 'bio_response') {\n this.handleResponse(data)\n } else if (data.type === 'bio_event') {\n this.handleEvent(data)\n }\n }\n\n private handleResponse(message: ResponseMessage): void {\n const pending = this.pendingRequests.get(message.id)\n if (!pending) return\n\n this.pendingRequests.delete(message.id)\n\n if (message.success) {\n pending.resolve(message.result)\n } else {\n const error = message.error ?? { code: BioErrorCodes.INTERNAL_ERROR, message: 'Unknown error' }\n pending.reject(createProviderError(error.code, error.message, error.data))\n }\n }\n\n private handleEvent(message: EventMessage): void {\n this.events.emit(message.event, ...message.args)\n\n // Handle built-in events\n if (message.event === 'connect') {\n this.connected = true\n } else if (message.event === 'disconnect') {\n this.connected = false\n }\n }\n\n private connect(): void {\n // Send handshake to host\n this.postMessage({\n type: 'bio_request',\n id: this.generateId(),\n method: 'bio_connect',\n params: [],\n })\n }\n\n private generateId(): string {\n return `bio_${Date.now()}_${++this.requestIdCounter}`\n }\n\n private postMessage(message: RequestMessage): void {\n if (window.parent === window) {\n console.warn('[BioSDK] Not running in iframe, cannot communicate with host')\n return\n }\n window.parent.postMessage(message, this.targetOrigin)\n }\n\n async request(args: RequestArguments): Promise {\n const id = this.generateId()\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n })\n\n this.postMessage({\n type: 'bio_request',\n id,\n method: args.method,\n params: args.params,\n })\n\n // Timeout after 5 minutes (for user interactions)\n setTimeout(() => {\n if (this.pendingRequests.has(id)) {\n this.pendingRequests.delete(id)\n reject(createProviderError(BioErrorCodes.INTERNAL_ERROR, 'Request timeout'))\n }\n }, 5 * 60 * 1000)\n })\n }\n\n on(event: string, handler: EventHandler): void {\n this.events.on(event, handler)\n }\n\n off(event: string, handler: EventHandler): void {\n this.events.off(event, handler)\n }\n\n isConnected(): boolean {\n return this.connected\n }\n}\n","/**\n * Bio SDK - Client SDK for Bio Ecosystem MiniApps\n *\n * Injects `window.bio` provider similar to `window.ethereum` in Web3 DApps.\n *\n * @example\n * ```typescript\n * import '@biochain/bio-sdk'\n *\n * // Now window.bio is available\n * const accounts = await window.bio.request({ method: 'bio_requestAccounts' })\n * ```\n */\n\nimport { BioProviderImpl } from './provider'\nimport type { BioProvider } from './types'\n\n// Re-export types\nexport * from './types'\nexport { EventEmitter } from './events'\nexport { BioProviderImpl } from './provider'\n\n// Extend Window interface\ndeclare global {\n interface Window {\n bio?: BioProvider\n }\n}\n\n/**\n * Initialize and inject the Bio provider into window.bio\n */\nexport function initBioProvider(targetOrigin = '*'): BioProvider {\n if (typeof window === 'undefined') {\n throw new Error('[BioSDK] Cannot initialize: window is not defined')\n }\n\n if (window.bio) {\n console.warn('[BioSDK] Provider already exists, returning existing instance')\n return window.bio\n }\n\n const provider = new BioProviderImpl(targetOrigin)\n window.bio = provider\n\n console.log('[BioSDK] Provider initialized')\n return provider\n}\n\n// Auto-initialize if running in browser\nif (typeof window !== 'undefined') {\n // Use a slight delay to ensure DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => initBioProvider())\n } else {\n initBioProvider()\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.umd.js","sources":["../src/types.ts","../src/events.ts","../src/provider.ts","../src/index.ts"],"sourcesContent":["/**\n * Bio SDK Types\n * EIP-1193 style provider interface for Bio ecosystem\n */\n\n/** Account information */\nexport interface BioAccount {\n address: string\n chain: string\n name?: string\n /** Public key (hex encoded) */\n publicKey: string\n}\n\n/** Transfer parameters */\nexport interface TransferParams {\n from: string\n to: string\n amount: string\n chain: string\n asset?: string\n}\n\n/** Unsigned transaction payload (chain-specific) */\nexport interface BioUnsignedTransaction {\n chainId: string\n data: unknown\n}\n\n/** Signed transaction payload (chain-specific) */\nexport interface BioSignedTransaction {\n chainId: string\n data: unknown\n signature: string\n}\n\n/** Provider request arguments */\nexport interface RequestArguments {\n method: string\n params?: unknown[]\n}\n\n/** Provider RPC error */\nexport interface ProviderRpcError extends Error {\n code: number\n data?: unknown\n}\n\n/** Event handler type */\nexport type EventHandler = (...args: T[]) => void\n\n/**\n * Bio Provider Interface (EIP-1193 style)\n */\nexport interface BioProvider {\n /** Make a request to the provider */\n request(args: RequestArguments): Promise\n\n /** Subscribe to an event */\n on(event: string, handler: EventHandler): void\n\n /** Unsubscribe from an event */\n off(event: string, handler: EventHandler): void\n\n /** Check if connected */\n isConnected(): boolean\n}\n\n/**\n * Bio method definitions\n */\nexport interface BioMethods {\n /** Request wallet accounts (shows connection UI) */\n bio_requestAccounts: () => Promise\n\n /** Get connected accounts (no UI) */\n bio_accounts: () => Promise\n\n /** Select an account (shows account picker UI) */\n bio_selectAccount: (opts?: { chain?: string }) => Promise\n\n /** Pick another wallet address (shows wallet picker UI) */\n bio_pickWallet: (opts?: { chain?: string; exclude?: string }) => Promise\n\n /** Sign a message, returns signature and public key (hex) */\n bio_signMessage: (params: { message: string; address: string }) => Promise<{ signature: string; publicKey: string }>\n\n /** Sign typed data, returns signature and public key (hex) */\n bio_signTypedData: (params: { data: object; address: string }) => Promise<{ signature: string; publicKey: string }>\n\n /** Create an unsigned transaction (no signature, no broadcast) */\n bio_createTransaction: (params: TransferParams) => Promise\n\n /** Sign an unsigned transaction (requires user confirmation) */\n bio_signTransaction: (params: { from: string; chain: string; unsignedTx: BioUnsignedTransaction }) => Promise\n\n /** Send a transaction */\n bio_sendTransaction: (params: TransferParams) => Promise<{ txHash: string }>\n\n /** Get current chain ID */\n bio_chainId: () => Promise\n\n /** Get balance */\n bio_getBalance: (params: { address: string; chain: string }) => Promise\n\n /** Close splash screen (indicates app is ready) */\n bio_closeSplashScreen: () => Promise\n}\n\n/**\n * Bio event definitions\n */\nexport interface BioEvents {\n /** Emitted when accounts change */\n accountsChanged: (accounts: BioAccount[]) => void\n\n /** Emitted when chain changes */\n chainChanged: (chainId: string) => void\n\n /** Emitted when connected */\n connect: (info: { chainId: string }) => void\n\n /** Emitted when disconnected */\n disconnect: (error: { code: number; message: string }) => void\n}\n\n/** Method names */\nexport type BioMethodName = keyof BioMethods\n\n/** Event names */\nexport type BioEventName = keyof BioEvents\n\n/** RPC error codes */\nexport const BioErrorCodes = {\n USER_REJECTED: 4001,\n UNAUTHORIZED: 4100,\n UNSUPPORTED_METHOD: 4200,\n DISCONNECTED: 4900,\n CHAIN_DISCONNECTED: 4901,\n INTERNAL_ERROR: -32603,\n INVALID_PARAMS: -32602,\n METHOD_NOT_FOUND: -32601,\n} as const\n\n/** Create a provider RPC error */\nexport function createProviderError(code: number, message: string, data?: unknown): ProviderRpcError {\n const error = new Error(message) as ProviderRpcError\n error.code = code\n error.data = data\n return error\n}\n","/**\n * Event emitter for Bio SDK\n */\n\nimport type { EventHandler } from './types'\n\nexport class EventEmitter {\n private handlers = new Map>()\n\n on(event: string, handler: EventHandler): void {\n let handlers = this.handlers.get(event)\n if (!handlers) {\n handlers = new Set()\n this.handlers.set(event, handlers)\n }\n handlers.add(handler)\n }\n\n off(event: string, handler: EventHandler): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n emit(event: string, ...args: unknown[]): void {\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(...args)\n } catch (error) {\n console.error(`[BioSDK] Error in event handler for \"${event}\":`, error)\n }\n })\n }\n }\n\n removeAllListeners(event?: string): void {\n if (event) {\n this.handlers.delete(event)\n } else {\n this.handlers.clear()\n }\n }\n}\n","/**\n * Bio Provider Implementation\n * Communicates with KeyApp host via postMessage\n */\n\nimport type { BioProvider, RequestArguments, EventHandler } from './types'\nimport { BioErrorCodes, createProviderError } from './types'\nimport { EventEmitter } from './events'\n\n/** Message sent to host */\ninterface RequestMessage {\n type: 'bio_request'\n id: string\n method: string\n params?: unknown[]\n}\n\n/** Response from host */\ninterface ResponseMessage {\n type: 'bio_response'\n id: string\n success: boolean\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\n/** Event from host */\ninterface EventMessage {\n type: 'bio_event'\n event: string\n args: unknown[]\n}\n\ntype HostMessage = ResponseMessage | EventMessage\n\nexport class BioProviderImpl implements BioProvider {\n private events = new EventEmitter()\n private pendingRequests = new Map void\n reject: (error: Error) => void\n }>()\n private requestIdCounter = 0\n private connected = false\n private readonly targetOrigin: string\n\n constructor(targetOrigin = '*') {\n this.targetOrigin = targetOrigin\n this.setupMessageListener()\n this.connect()\n }\n\n private setupMessageListener(): void {\n window.addEventListener('message', this.handleMessage.bind(this))\n }\n\n private handleMessage(event: MessageEvent): void {\n const data = event.data as HostMessage\n if (!data || typeof data !== 'object') return\n\n if (data.type === 'bio_response') {\n this.handleResponse(data)\n } else if (data.type === 'bio_event') {\n this.handleEvent(data)\n }\n }\n\n private handleResponse(message: ResponseMessage): void {\n const pending = this.pendingRequests.get(message.id)\n if (!pending) return\n\n this.pendingRequests.delete(message.id)\n\n if (message.success) {\n pending.resolve(message.result)\n } else {\n const error = message.error ?? { code: BioErrorCodes.INTERNAL_ERROR, message: 'Unknown error' }\n pending.reject(createProviderError(error.code, error.message, error.data))\n }\n }\n\n private handleEvent(message: EventMessage): void {\n this.events.emit(message.event, ...message.args)\n\n // Handle built-in events\n if (message.event === 'connect') {\n this.connected = true\n } else if (message.event === 'disconnect') {\n this.connected = false\n }\n }\n\n private connect(): void {\n // Send handshake to host\n this.postMessage({\n type: 'bio_request',\n id: this.generateId(),\n method: 'bio_connect',\n params: [],\n })\n }\n\n private generateId(): string {\n return `bio_${Date.now()}_${++this.requestIdCounter}`\n }\n\n private postMessage(message: RequestMessage): void {\n if (window.parent === window) {\n console.warn('[BioSDK] Not running in iframe, cannot communicate with host')\n return\n }\n window.parent.postMessage(message, this.targetOrigin)\n }\n\n async request(args: RequestArguments): Promise {\n const id = this.generateId()\n\n return new Promise((resolve, reject) => {\n this.pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n })\n\n this.postMessage({\n type: 'bio_request',\n id,\n method: args.method,\n params: args.params,\n })\n\n // Timeout after 5 minutes (for user interactions)\n setTimeout(() => {\n if (this.pendingRequests.has(id)) {\n this.pendingRequests.delete(id)\n reject(createProviderError(BioErrorCodes.INTERNAL_ERROR, 'Request timeout'))\n }\n }, 5 * 60 * 1000)\n })\n }\n\n on(event: string, handler: EventHandler): void {\n this.events.on(event, handler)\n }\n\n off(event: string, handler: EventHandler): void {\n this.events.off(event, handler)\n }\n\n isConnected(): boolean {\n return this.connected\n }\n}\n","/**\n * Bio SDK - Client SDK for Bio Ecosystem MiniApps\n *\n * Injects `window.bio` provider similar to `window.ethereum` in Web3 DApps.\n *\n * @example\n * ```typescript\n * import '@biochain/bio-sdk'\n *\n * // Now window.bio is available\n * const accounts = await window.bio.request({ method: 'bio_requestAccounts' })\n * ```\n */\n\nimport { BioProviderImpl } from './provider'\nimport type { BioProvider } from './types'\n\n// Re-export types\nexport * from './types'\nexport { EventEmitter } from './events'\nexport { BioProviderImpl } from './provider'\n\n// Extend Window interface\ndeclare global {\n interface Window {\n bio?: BioProvider\n }\n}\n\n/**\n * Initialize and inject the Bio provider into window.bio\n */\nexport function initBioProvider(targetOrigin = '*'): BioProvider {\n if (typeof window === 'undefined') {\n throw new Error('[BioSDK] Cannot initialize: window is not defined')\n }\n\n if (window.bio) {\n console.warn('[BioSDK] Provider already exists, returning existing instance')\n return window.bio\n }\n\n const provider = new BioProviderImpl(targetOrigin)\n window.bio = provider\n\n console.log('[BioSDK] Provider initialized')\n return provider\n}\n\n// Auto-initialize if running in browser\nif (typeof window !== 'undefined') {\n // Use a slight delay to ensure DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => initBioProvider())\n } else {\n initBioProvider()\n }\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file