{"version":3,"file":"dapp-post-message-channel.mjs","names":["#id","#popup","#hostOrigin","#hostPathname","#appName","#promise","#resolve","#reject","#extraRequestOptions","#interval","#cleanup","#isSendCalled","#listener","#version"],"sources":["../../src/web-wallet-channel/dapp-post-message-channel.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { safeParse } from 'valibot';\nimport type { JsonData, RequestDataType, RequestType } from './requests.js';\nimport type { ResponseTypes } from './responses.js';\nimport { Response } from './responses.js';\nimport { promiseWithResolvers } from '@mysten/utils';\nimport { getClientMetadata } from './utils.js';\n\ntype DappPostMessageChannelOptions = {\n\tappName: string;\n\thostOrigin: string;\n\thostPathname?: string;\n\textraRequestOptions?: Record<string, JsonData>;\n\tpopupWindow?: Window;\n};\n\nexport class DappPostMessageChannel {\n\t#popup: Window;\n\t#version = '1' as const;\n\t#id: string;\n\t#hostOrigin: string;\n\t#hostPathname: string;\n\t#appName: string;\n\t#extraRequestOptions?: Record<string, JsonData>;\n\t#promise: Promise<unknown>;\n\t#resolve: (data: unknown) => void;\n\t#reject: (error: Error) => void;\n\t#interval: ReturnType<typeof setInterval> | null = null;\n\t#isSendCalled: boolean = false;\n\n\tconstructor({\n\t\tappName,\n\t\thostOrigin,\n\t\thostPathname = 'dapp-request',\n\t\textraRequestOptions,\n\t\tpopupWindow,\n\t}: DappPostMessageChannelOptions) {\n\t\tconst popup = popupWindow ?? window.open('about:blank', '_blank');\n\n\t\tif (!popup) {\n\t\t\tthrow new Error('Failed to open new window');\n\t\t}\n\n\t\tthis.#id = crypto.randomUUID();\n\t\tthis.#popup = popup;\n\t\tthis.#hostOrigin = hostOrigin;\n\t\tthis.#hostPathname = hostPathname;\n\t\tthis.#appName = appName;\n\n\t\tconst { promise, resolve, reject } = promiseWithResolvers();\n\n\t\tthis.#promise = promise;\n\t\tthis.#resolve = resolve;\n\t\tthis.#reject = reject;\n\t\tthis.#extraRequestOptions = extraRequestOptions;\n\t\tthis.#interval = setInterval(() => {\n\t\t\ttry {\n\t\t\t\tif (this.#popup.closed) {\n\t\t\t\t\tthis.#cleanup();\n\t\t\t\t\treject(new Error('User closed the wallet window'));\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// This can error during the login flow, but that's fine.\n\t\t\t}\n\t\t}, 1000);\n\t}\n\n\tsend<T extends RequestDataType['type']>({\n\t\ttype,\n\t\t...data\n\t}: {\n\t\ttype: T;\n\t} & Extract<RequestDataType, { type: T }>): Promise<ResponseTypes[T]> {\n\t\tif (this.#popup.closed) {\n\t\t\tthrow new Error('User closed the wallet window');\n\t\t}\n\n\t\tif (this.#isSendCalled) {\n\t\t\tthrow new Error('send() can only be called once');\n\t\t}\n\n\t\tthis.#isSendCalled = true;\n\n\t\twindow.addEventListener('message', this.#listener);\n\n\t\tconst requestData = {\n\t\t\tversion: this.#version,\n\t\t\trequestId: this.#id,\n\t\t\tappUrl: window.location.href.split('#')[0],\n\t\t\tappName: this.#appName,\n\t\t\tpayload: {\n\t\t\t\ttype,\n\t\t\t\t...data,\n\t\t\t} as RequestDataType,\n\t\t\tmetadata: getClientMetadata(),\n\t\t\textraRequestOptions: this.#extraRequestOptions,\n\t\t} satisfies RequestType;\n\t\tconst encodedRequestData = encodeURIComponent(btoa(JSON.stringify(requestData)));\n\n\t\tthis.#popup.location.assign(`${this.#hostOrigin}/${this.#hostPathname}#${encodedRequestData}`);\n\n\t\treturn this.#promise as Promise<ResponseTypes[T]>;\n\t}\n\n\tclose() {\n\t\tthis.#cleanup();\n\t\tthis.#popup.close();\n\t}\n\n\t#listener = (event: MessageEvent) => {\n\t\tif (event.origin !== this.#hostOrigin) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { success, output } = safeParse(Response, event.data);\n\n\t\tif (!success || output.id !== this.#id) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#cleanup();\n\n\t\tif (output.payload.type === 'reject') {\n\t\t\tthis.#reject(new Error(output.payload.reason || 'User rejected the request'));\n\t\t} else if (output.payload.type === 'resolve') {\n\t\t\tthis.#resolve(output.payload.data);\n\t\t}\n\t};\n\n\t#cleanup() {\n\t\tif (this.#interval) {\n\t\t\tclearInterval(this.#interval);\n\t\t\tthis.#interval = null;\n\t\t}\n\t\twindow.removeEventListener('message', this.#listener);\n\t}\n}\n"],"mappings":";;;;;;AAkBA,IAAa,yBAAb,MAAoC;CACnC;CACA,WAAW;CACX;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,YAAmD;CACnD,gBAAyB;CAEzB,YAAY,EACX,SACA,YACA,eAAe,gBACf,qBACA,eACiC;EACjC,MAAM,QAAQ,eAAe,OAAO,KAAK,eAAe,SAAS;AAEjE,MAAI,CAAC,MACJ,OAAM,IAAI,MAAM,4BAA4B;AAG7C,QAAKA,KAAM,OAAO,YAAY;AAC9B,QAAKC,QAAS;AACd,QAAKC,aAAc;AACnB,QAAKC,eAAgB;AACrB,QAAKC,UAAW;EAEhB,MAAM,EAAE,SAAS,SAAS,WAAW,sBAAsB;AAE3D,QAAKC,UAAW;AAChB,QAAKC,UAAW;AAChB,QAAKC,SAAU;AACf,QAAKC,sBAAuB;AAC5B,QAAKC,WAAY,kBAAkB;AAClC,OAAI;AACH,QAAI,MAAKR,MAAO,QAAQ;AACvB,WAAKS,SAAU;AACf,4BAAO,IAAI,MAAM,gCAAgC,CAAC;;WAE5C;KAGN,IAAK;;CAGT,KAAwC,EACvC,MACA,GAAG,QAGkE;AACrE,MAAI,MAAKT,MAAO,OACf,OAAM,IAAI,MAAM,gCAAgC;AAGjD,MAAI,MAAKU,aACR,OAAM,IAAI,MAAM,iCAAiC;AAGlD,QAAKA,eAAgB;AAErB,SAAO,iBAAiB,WAAW,MAAKC,SAAU;EAElD,MAAM,cAAc;GACnB,SAAS,MAAKC;GACd,WAAW,MAAKb;GAChB,QAAQ,OAAO,SAAS,KAAK,MAAM,IAAI,CAAC;GACxC,SAAS,MAAKI;GACd,SAAS;IACR;IACA,GAAG;IACH;GACD,UAAU,mBAAmB;GAC7B,qBAAqB,MAAKI;GAC1B;EACD,MAAM,qBAAqB,mBAAmB,KAAK,KAAK,UAAU,YAAY,CAAC,CAAC;AAEhF,QAAKP,MAAO,SAAS,OAAO,GAAG,MAAKC,WAAY,GAAG,MAAKC,aAAc,GAAG,qBAAqB;AAE9F,SAAO,MAAKE;;CAGb,QAAQ;AACP,QAAKK,SAAU;AACf,QAAKT,MAAO,OAAO;;CAGpB,aAAa,UAAwB;AACpC,MAAI,MAAM,WAAW,MAAKC,WACzB;EAGD,MAAM,EAAE,SAAS,WAAW,UAAU,UAAU,MAAM,KAAK;AAE3D,MAAI,CAAC,WAAW,OAAO,OAAO,MAAKF,GAClC;AAGD,QAAKU,SAAU;AAEf,MAAI,OAAO,QAAQ,SAAS,SAC3B,OAAKH,OAAQ,IAAI,MAAM,OAAO,QAAQ,UAAU,4BAA4B,CAAC;WACnE,OAAO,QAAQ,SAAS,UAClC,OAAKD,QAAS,OAAO,QAAQ,KAAK;;CAIpC,WAAW;AACV,MAAI,MAAKG,UAAW;AACnB,iBAAc,MAAKA,SAAU;AAC7B,SAAKA,WAAY;;AAElB,SAAO,oBAAoB,WAAW,MAAKG,SAAU"}