Skip to content

Commit

Permalink
Merge pull request #1865 from aeternity/feature/rpc-fixes
Browse files Browse the repository at this point in the history
Aepp-wallet connection fixes
  • Loading branch information
davidyuk committed Jul 27, 2023
2 parents 49e57e7 + 1d84843 commit 0c97015
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 77 deletions.
2 changes: 0 additions & 2 deletions examples/browser/aepp/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
</template>

<script>
import { mapState } from 'vuex';
import Connect from './Connect.vue';
import Basic from './Basic.vue';
import Contracts from './Contracts.vue';
Expand All @@ -61,7 +60,6 @@ export default {
Connect, Basic, Contracts, PayForTx, TypedData, DelegationSignature,
},
data: () => ({ view: '' }),
computed: mapState(['aeSdk']),
};
</script>

Expand Down
75 changes: 49 additions & 26 deletions examples/browser/aepp/src/Connect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,26 @@
</label>
<div><input v-model="reverseIframeWalletUrl"></div>
</div>

<button
v-if="walletConnected"
@click="disconnect"
>
Disconnect
</button>
<button
v-if="connectMethod && !walletConnected"
v-else-if="connectMethod"
:disabled="walletConnecting"
@click="connect"
>
Connect
</button>

<button
v-if="walletConnected"
@click="disconnect"
v-if="cancelWalletDetection"
@click="cancelWalletDetection"
>
Disconnect
Cancel detection
</button>
</div>

Expand All @@ -34,6 +42,7 @@
<div>
{{
(walletConnected && 'Wallet connected')
|| (cancelWalletDetection && 'Wallet detection')
|| (walletConnecting && 'Wallet connecting')
|| 'Ready to connect to wallet'
}}
Expand All @@ -48,7 +57,7 @@

<script>
import {
walletDetector, BrowserWindowMessageConnection, RpcConnectionDenyError,
walletDetector, BrowserWindowMessageConnection, RpcConnectionDenyError, RpcRejectedByUserError,
} from '@aeternity/aepp-sdk';
import { mapState } from 'vuex';
Expand All @@ -60,6 +69,7 @@ export default {
reverseIframe: null,
reverseIframeWalletUrl: process.env.VUE_APP_WALLET_URL ?? 'http://localhost:9000',
walletInfo: null,
cancelWalletDetection: null,
}),
computed: {
...mapState(['aeSdk']),
Expand All @@ -69,32 +79,40 @@ export default {
},
},
methods: {
async scanForWallets() {
return new Promise((resolve) => {
let stopScan;
const handleWallets = async ({ wallets, newWallet }) => {
newWallet = newWallet || Object.values(wallets)[0];
async detectWallets() {
if (this.connectMethod === 'reverse-iframe') {
this.reverseIframe = document.createElement('iframe');
this.reverseIframe.src = this.reverseIframeWalletUrl;
this.reverseIframe.style.display = 'none';
document.body.appendChild(this.reverseIframe);
}
const connection = new BrowserWindowMessageConnection();
return new Promise((resolve, reject) => {
const stopDetection = walletDetector(connection, async ({ newWallet }) => {
if (confirm(`Do you want to connect to wallet ${newWallet.info.name} with id ${newWallet.info.id}`)) {
stopScan();
stopDetection();
resolve(newWallet.getConnection());
this.cancelWalletDetection = null;
}
});
this.cancelWalletDetection = () => {
reject(new Error('Wallet detection cancelled'));
stopDetection();
this.cancelWalletDetection = null;
if (this.reverseIframe) this.reverseIframe.remove();
};
const scannerConnection = new BrowserWindowMessageConnection();
stopScan = walletDetector(scannerConnection, handleWallets);
});
},
async connect() {
this.walletConnecting = true;
this.aeSdk.onDisconnect = () => {
this.walletConnected = false;
this.walletInfo = null;
this.$store.commit('setAddress', undefined);
if (this.reverseIframe) this.reverseIframe.remove();
};
try {
if (this.connectMethod === 'reverse-iframe') {
this.reverseIframe = document.createElement('iframe');
this.reverseIframe.src = this.reverseIframeWalletUrl;
this.reverseIframe.style.display = 'none';
document.body.appendChild(this.reverseIframe);
}
const connection = await this.scanForWallets();
const connection = await this.detectWallets();
try {
this.walletInfo = await this.aeSdk.connectToWallet(connection);
} catch (error) {
Expand All @@ -104,14 +122,19 @@ export default {
this.walletConnected = true;
const { address: { current } } = await this.aeSdk.subscribeAddress('subscribe', 'connected');
this.$store.commit('setAddress', Object.keys(current)[0]);
} catch (error) {
if (
error.message === 'Wallet detection cancelled'
|| error instanceof RpcConnectionDenyError
|| error instanceof RpcRejectedByUserError
) return;
throw error;
} finally {
this.walletConnecting = false;
}
},
async disconnect() {
await this.aeSdk.disconnectWallet();
this.walletConnected = false;
if (this.reverseIframe) this.reverseIframe.remove();
disconnect() {
this.aeSdk.disconnectWallet();
},
},
};
Expand Down
1 change: 0 additions & 1 deletion examples/browser/aepp/src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const store = createStore({
store.commit('setNetworkId', networkId);
},
onAddressChange: ({ current }) => store.commit('setAddress', Object.keys(current)[0]),
onDisconnect: () => alert('Aepp is disconnected'),
})),
},
mutations: {
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/aepp/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ body {
}

button {
@extend .w-32, .p-2, .m-2, .rounded-full, .bg-purple-500, .text-white, .text-xs;
@extend .w-40, .p-2, .m-2, .rounded-full, .bg-purple-500, .text-white, .text-xs;

&:disabled {
@extend .bg-purple-300, .cursor-not-allowed;
Expand Down
90 changes: 67 additions & 23 deletions examples/browser/wallet-iframe/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,26 @@
<div>Balance</div>
<Value :value="balancePromise" />
</div>
<div>
<div>RPC client</div>
<div>status: {{ clientStatus ?? 'no client' }}, id: {{ clientId ?? 'not defined' }}</div>
</div>

<button @click="switchAccount">Switch Account</button>
<button @click="switchNode">Switch Node</button>
<button @click="disconnect">Disconnect</button>

<button
v-if="clientStatus === 'CONNECTED'"
@click="disconnect"
>
Disconnect
</button>
<button
v-else
@click="() => (stopSharingWalletInfo ?? shareWalletInfo)()"
>
{{ stopSharingWalletInfo ? 'Stop sharing' : 'Share wallet info' }}
</button>
</div>

<iframe
Expand All @@ -30,7 +46,7 @@
<script>
import {
MemoryAccount, generateKeyPair, AeSdkWallet, Node, CompilerHttp,
BrowserWindowMessageConnection, METHODS, WALLET_TYPE,
BrowserWindowMessageConnection, METHODS, WALLET_TYPE, RPC_STATUS,
RpcConnectionDenyError, RpcRejectedByUserError, unpackTx, decodeFateValue,
} from '@aeternity/aepp-sdk';
import Value from './Value.vue';
Expand All @@ -43,24 +59,42 @@ export default {
nodeName: '',
address: '',
balancePromise: null,
clientId: null,
clientStatus: null,
stopSharingWalletInfo: null,
}),
methods: {
async shareWalletInfo(clientId, { interval = 5000, attemps = 5 } = {}) {
this.aeSdk.shareWalletInfo(clientId);
while (attemps) {
await new Promise((resolve) => {
setTimeout(resolve, interval);
});
this.aeSdk.shareWalletInfo(clientId);
attemps -= 1;
shareWalletInfo({ interval = 5000, attempts = 5 } = {}) {
const target = this.runningInFrame ? window.parent : this.$refs.aepp.contentWindow;
const connection = new BrowserWindowMessageConnection({ target });
this.clientId = this.aeSdk.addRpcClient(connection);

this.aeSdk.shareWalletInfo(this.clientId);
const intervalId = setInterval(() => {
this.aeSdk.shareWalletInfo(this.clientId);
attempts -= 1;
if (!attempts) return this.stopSharingWalletInfo();
}, interval);

this.stopSharingWalletInfo = () => {
clearInterval(intervalId);
// TODO: replace with clientStatus
const client = this.aeSdk._getClient(this.clientId);
if (client.status === RPC_STATUS.WAITING_FOR_CONNECTION_REQUEST) {
this.aeSdk.removeRpcClient(this.clientId);
}
this.stopSharingWalletInfo = null;
}
console.log('Finish sharing wallet info');
},
disconnect() {
Object.values(this.aeSdk.rpcClients).forEach((client) => {
client.notify(METHODS.closeConnection);
client.disconnect();
});
// TODO: move to removeRpcClient (would be a semi-breaking change)
const client = this.aeSdk._getClient(this.clientId);
if (client.status === RPC_STATUS.CONNECTED) {
client.rpc.notify(METHODS.closeConnection, null);
}

this.aeSdk.removeRpcClient(this.clientId);
this.clientId = null;
},
async switchAccount() {
this.address = this.aeSdk.addresses().find((a) => a !== this.address);
Expand All @@ -72,6 +106,14 @@ export default {
.find((name) => name !== this.nodeName);
this.aeSdk.selectNode(this.nodeName);
},
updateClientStatus() {
if (!this.clientId) {
this.clientStatus = null;
return;
}
const client = this.aeSdk._getClient(this.clientId);
this.clientStatus = client.status;
},
},
mounted() {
const aeppInfo = {};
Expand Down Expand Up @@ -151,7 +193,6 @@ export default {
}
}

let clientId;
this.aeSdk = new AeSdkWallet({
id: window.origin,
type: WALLET_TYPE.window,
Expand All @@ -170,29 +211,32 @@ export default {
throw new RpcConnectionDenyError();
}
aeppInfo[aeppId] = params;
setTimeout(() => this.stopSharingWalletInfo());
},
onSubscription: genConfirmCallback('subscription'),
onAskAccounts: genConfirmCallback('get accounts'),
onDisconnect() {
this.shareWalletInfo(clientId);
onDisconnect: (clientId) => {
console.log('disconnected client', clientId);
this.clientId = null;
},
});

if (this.runningInFrame) this.shareWalletInfo();

this.nodeName = this.aeSdk.selectedNodeName;
[this.address] = this.aeSdk.addresses();

const target = this.runningInFrame ? window.parent : this.$refs.aepp.contentWindow;
const connection = new BrowserWindowMessageConnection({ target });
clientId = this.aeSdk.addRpcClient(connection);
this.shareWalletInfo(clientId);
this.$watch(
({ address, nodeName }) => [address, nodeName],
([address]) => {
this.balancePromise = this.aeSdk.getBalance(address);
},
{ immediate: true },
);

// TODO: replace setInterval with subscription after refactoring
setInterval(() => this.updateClientStatus(), 1000);
this.$watch(({ clientId }) => [clientId], () => this.updateClientStatus(), { immediate: true });
},
};
</script>
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/wallet-iframe/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ body {
}

button {
@extend .w-32, .p-2, .m-2, .rounded-full, .bg-purple-500, .text-white, .text-xs;
@extend .w-40, .p-2, .m-2, .rounded-full, .bg-purple-500, .text-white, .text-xs;

&:disabled {
@extend .bg-purple-300, .cursor-not-allowed;
Expand Down
2 changes: 1 addition & 1 deletion examples/browser/wallet-web-extension/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ body {
}

button {
@extend .w-32, .p-2, .m-2, .rounded-full, .bg-purple-500, .text-white, .text-xs;
@extend .w-40, .p-2, .m-2, .rounded-full, .bg-purple-500, .text-white, .text-xs;

&:disabled {
@extend .bg-purple-300, .cursor-not-allowed;
Expand Down

0 comments on commit 0c97015

Please sign in to comment.