diff --git a/examples/browser/wallet-iframe/src/App.vue b/examples/browser/wallet-iframe/src/App.vue index 5b66c02b9d..8c4113aca6 100644 --- a/examples/browser/wallet-iframe/src/App.vue +++ b/examples/browser/wallet-iframe/src/App.vue @@ -76,20 +76,27 @@ export default { }, mounted() { const aeppInfo = {}; - const genConfirmCallback = (actionName) => (aeppId) => { - if (!confirm(`Client ${aeppInfo[aeppId].name} with id ${aeppId} want to ${actionName}`)) { + const genConfirmCallback = (actionName) => (aeppId, parameters, origin) => { + if (!confirm([ + `Client ${aeppInfo[aeppId].name} with id ${aeppId} at ${origin} want to ${actionName}`, + JSON.stringify(parameters, null, 2), + ].join('\n'))) { throw new RpcRejectedByUserError(); } }; class AccountMemoryProtected extends MemoryAccount { - async signTransaction(tx, { aeppRpcClientId: id, ...options } = {}) { - if (id != null) genConfirmCallback(`sign transaction ${tx}`)(id); + async signTransaction(tx, { aeppRpcClientId: id, aeppOrigin, ...options } = {}) { + if (id != null) { + genConfirmCallback(`sign transaction ${tx}`)(id, options, aeppOrigin); + } return super.signTransaction(tx, options); } - async signMessage(message, { aeppRpcClientId: id, ...options } = {}) { - if (id != null) genConfirmCallback(`sign message ${message}`)(id); + async signMessage(message, { aeppRpcClientId: id, aeppOrigin, ...options } = {}) { + if (id != null) { + genConfirmCallback(`sign message ${message}`)(id, options, aeppOrigin); + } return super.signMessage(message, options); } @@ -113,8 +120,8 @@ export default { ], onCompiler: new CompilerHttp('https://v7.compiler.aepps.com'), name: 'Wallet Iframe', - onConnection: (aeppId, params) => { - if (!confirm(`Client ${params.name} with id ${aeppId} want to connect`)) { + onConnection: (aeppId, params, origin) => { + if (!confirm(`Client ${params.name} with id ${aeppId} at ${origin} want to connect`)) { throw new RpcConnectionDenyError(); } aeppInfo[aeppId] = params; diff --git a/examples/browser/wallet-web-extension/src/background.js b/examples/browser/wallet-web-extension/src/background.js index 0bdbe9ceab..61c03648f8 100644 --- a/examples/browser/wallet-web-extension/src/background.js +++ b/examples/browser/wallet-web-extension/src/background.js @@ -5,20 +5,27 @@ import { } from '@aeternity/aepp-sdk'; const aeppInfo = {}; -const genConfirmCallback = (actionName) => (aeppId) => { - if (!confirm(`Client ${aeppInfo[aeppId].name} with id ${aeppId} want to ${actionName}`)) { +const genConfirmCallback = (actionName) => (aeppId, parameters, origin) => { + if (!confirm([ + `Client ${aeppInfo[aeppId].name} with id ${aeppId} at ${origin} want to ${actionName}`, + JSON.stringify(parameters, null, 2), + ].join('\n'))) { throw new RpcRejectedByUserError(); } }; class AccountMemoryProtected extends MemoryAccount { - async signTransaction(tx, { aeppRpcClientId: id, ...options } = {}) { - if (id != null) genConfirmCallback(`sign transaction ${tx}`)(id); + async signTransaction(tx, { aeppRpcClientId: id, aeppOrigin, ...options } = {}) { + if (id != null) { + genConfirmCallback(`sign transaction ${tx}`)(id, options, aeppOrigin); + } return super.signTransaction(tx, options); } - async signMessage(message, { aeppRpcClientId: id, ...options } = {}) { - if (id != null) genConfirmCallback(`sign message ${message}`)(id); + async signMessage(message, { aeppRpcClientId: id, aeppOrigin, ...options } = {}) { + if (id != null) { + genConfirmCallback(`sign message ${message}`)(id, options, aeppOrigin); + } return super.signMessage(message, options); } @@ -41,9 +48,8 @@ const aeSdk = new AeSdkWallet({ id: browser.runtime.id, type: WALLET_TYPE.extension, name: 'Wallet WebExtension', - // Hook for sdk registration - onConnection(aeppId, params) { - if (!confirm(`Aepp ${params.name} with id ${aeppId} wants to connect`)) { + onConnection: (aeppId, params, origin) => { + if (!confirm(`Client ${params.name} with id ${aeppId} at ${origin} want to connect`)) { throw new RpcConnectionDenyError(); } aeppInfo[aeppId] = params; diff --git a/src/aepp-wallet-communication/connection/BrowserRuntime.ts b/src/aepp-wallet-communication/connection/BrowserRuntime.ts index 68dab6178b..2485c1ced6 100644 --- a/src/aepp-wallet-communication/connection/BrowserRuntime.ts +++ b/src/aepp-wallet-communication/connection/BrowserRuntime.ts @@ -43,7 +43,8 @@ export default class BrowserRuntimeConnection extends BrowserConnection { super.connect(onMessage, onDisconnect); this.port.onMessage.addListener((message, port) => { this.receiveMessage(message); - onMessage(message, port.name, port); + // TODO: make `origin` optional because sender url is not available on aepp side + onMessage(message, port.sender?.url ?? '', port); }); this.port.onDisconnect.addListener(onDisconnect); } diff --git a/test/integration/rpc.ts b/test/integration/rpc.ts index 67023f3064..f7191df9df 100644 --- a/test/integration/rpc.ts +++ b/test/integration/rpc.ts @@ -71,7 +71,7 @@ const WindowPostMessageFake = ( this.messages.push(msg); setTimeout(() => { if (typeof this.listener === 'function') { - this.listener({ data: msg, origin: 'testOrigin', source }); + this.listener({ data: msg, origin: 'http://origin.test', source }); } }); }, @@ -213,11 +213,19 @@ describe('Aepp<->Wallet', function aeppWallet() { }); it('Subscribe to address: wallet accept', async () => { - wallet.onSubscription = () => {}; + let checkPromise; + wallet.onSubscription = (id, params, origin) => { + checkPromise = Promise.resolve().then(() => { + expect(id.split('-').length).to.be.equal(5); + expect(params).to.be.eql({ type: 'subscribe', value: 'connected' }); + expect(origin).to.be.equal('http://origin.test'); + }); + }; await aepp.subscribeAddress(SUBSCRIPTION_TYPES.subscribe, 'connected'); await aepp.subscribeAddress(SUBSCRIPTION_TYPES.unsubscribe, 'connected'); const subscriptionResponse = await aepp.subscribeAddress(SUBSCRIPTION_TYPES.subscribe, 'connected'); + await checkPromise; subscriptionResponse.subscription.should.be.an('array'); subscriptionResponse.subscription.filter((e) => e === 'connected').length.should.be.equal(1); subscriptionResponse.address.current.should.be.an('object'); @@ -250,10 +258,18 @@ describe('Aepp<->Wallet', function aeppWallet() { }); it('Ask for address: subscribed for accounts -> wallet accept', async () => { - wallet.onAskAccounts = () => {}; + let checkPromise; + wallet.onAskAccounts = (id, params, origin) => { + checkPromise = Promise.resolve().then(() => { + expect(id.split('-').length).to.be.equal(5); + expect(params).to.be.equal(undefined); + expect(origin).to.be.equal('http://origin.test'); + }); + }; const addressees = await aepp.askAddresses(); addressees.length.should.be.equal(2); addressees[0].should.be.equal(account.address); + await checkPromise; }); it('Not authorize', async () => { @@ -266,7 +282,9 @@ describe('Aepp<->Wallet', function aeppWallet() { }); it('Sign transaction: wallet deny', async () => { - wallet._resolveAccount().signTransaction = () => { + let origin; + wallet._resolveAccount().signTransaction = (tx, { aeppOrigin }) => { + origin = aeppOrigin; throw new RpcRejectedByUserError(); }; const tx = await aepp.buildTx(Tag.SpendTx, { @@ -277,6 +295,7 @@ describe('Aepp<->Wallet', function aeppWallet() { }); await expect(aepp.signTransaction(tx)).to.be.eventually .rejectedWith('Operation rejected by user').with.property('code', 4); + expect(origin).to.be.equal('http://origin.test'); }); it('Sign transaction: fails with unknown error', async () => { @@ -346,11 +365,14 @@ describe('Aepp<->Wallet', function aeppWallet() { }); it('Sign message: rejected', async () => { - wallet._resolveAccount().signMessage = () => { + let origin; + wallet._resolveAccount().signMessage = (message, { aeppOrigin } = {}) => { + origin = aeppOrigin; throw new RpcRejectedByUserError(); }; await expect(aepp.signMessage('test')).to.be.eventually .rejectedWith('Operation rejected by user').with.property('code', 4); + expect(origin).to.be.equal('http://origin.test'); }); it('Sign message', async () => { @@ -490,7 +512,6 @@ describe('Aepp<->Wallet', function aeppWallet() { }); describe('New RPC Wallet-AEPP: Bind wallet node to AEPP', () => { - const keypair = generateKeyPair(); let aepp: AeSdkAepp; let wallet: AeSdkWallet; @@ -520,21 +541,11 @@ describe('Aepp<->Wallet', function aeppWallet() { }); it('Subscribe to address: wallet accept', async () => { - const accounts = { - connected: { [keypair.publicKey]: {} }, - current: wallet.addresses().reduce((acc, v) => ({ ...acc, [v]: {} }), {}), - }; - wallet.onSubscription = () => accounts; + wallet.onSubscription = () => {}; await aepp.subscribeAddress(SUBSCRIPTION_TYPES.subscribe, 'connected'); await aepp.subscribeAddress(SUBSCRIPTION_TYPES.unsubscribe, 'connected'); const subscriptionResponse = await aepp.subscribeAddress(SUBSCRIPTION_TYPES.subscribe, 'connected'); - subscriptionResponse.subscription.should.be.an('array'); - subscriptionResponse.subscription.filter((e) => e === 'connected').length.should.be.equal(1); - subscriptionResponse.address.current.should.be.an('object'); - Object.keys(subscriptionResponse.address.current)[0].should.be.equal(account.address); - subscriptionResponse.address.connected.should.be.an('object'); - Object.keys(subscriptionResponse.address.connected).length.should.be.equal(0); }); it('Sign by wallet and broadcast transaction by aepp ', async () => {