-
Notifications
You must be signed in to change notification settings - Fork 54
/
ui.ts
158 lines (138 loc) · 5.84 KB
/
ui.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* eslint-disable no-use-before-define */
import { BackgroundServices, UserPromptService, adaPriceProperties, env, logger } from './util';
import { Cardano } from '@cardano-sdk/core';
import {
RemoteApiPropertyType,
WalletManagerUi,
consumeRemoteApi,
consumeSupplyDistributionTracker,
exposeApi
} from '@cardano-sdk/web-extension';
import { adaPriceServiceChannel, getObservableWalletName, userPromptServiceChannel, walletName } from './const';
import { cryptoProviderFactory, keyManagementFactory } from '../../../src';
import { combineLatest, firstValueFrom, of } from 'rxjs';
import { runtime } from 'webextension-polyfill';
import { setupWallet } from '@cardano-sdk/wallet';
const api: UserPromptService = {
allowOrigin(origin) {
const container = document.querySelector<HTMLDivElement>('#requestAccess')!;
container.style.display = 'block';
document.querySelector<HTMLSpanElement>('#requestAccessOrigin')!.textContent = origin;
const btnGrant = document.querySelector<HTMLButtonElement>('#requestAccessGrant')!;
const btnDeny = document.querySelector<HTMLButtonElement>('#requestAccessDeny')!;
return new Promise((resolve) => {
const done = async (grant: boolean) => {
btnGrant.removeEventListener('click', grantListener);
btnDeny.removeEventListener('click', denyListener);
container.style.display = 'none';
resolve(grant);
};
const grantListener = () => done(true);
const denyListener = () => done(false);
btnGrant.addEventListener('click', grantListener);
btnDeny.addEventListener('click', denyListener);
});
}
};
exposeApi<UserPromptService>(
{
api$: of(api),
baseChannel: userPromptServiceChannel,
properties: { allowOrigin: RemoteApiPropertyType.MethodReturningPromise }
},
{ logger, runtime }
);
// Consume background services
const backgroundServices = consumeRemoteApi<BackgroundServices>(
{
baseChannel: adaPriceServiceChannel,
properties: adaPriceProperties
},
{ logger, runtime }
);
backgroundServices.adaUsd$.subscribe((price) => (document.querySelector('#adaPrice')!.textContent = price.toFixed(2)));
document
.querySelector<HTMLButtonElement>('#clearAllowList')!
.addEventListener('click', backgroundServices.clearAllowList);
// SupplyDistributionTracker is used only for extension messaging demo purposes testing purposes.
// It will not switch when the wallet is changed
const supplyDistribution = consumeSupplyDistributionTracker({ walletName }, { logger, runtime });
combineLatest([supplyDistribution.lovelaceSupply$, supplyDistribution.stake$]).subscribe(
([lovelaceSupply, stake]) =>
(document.querySelector('#supplyDistribution')!.textContent = `${stake.live} out of ${lovelaceSupply.total}`)
);
const setAddress = (text: string): void => {
document.querySelector('#address')!.textContent = text;
};
const setBalance = (text: string): void => {
document.querySelector('#balance')!.textContent = text;
};
const setSignature = (text: string): void => {
document.querySelector('#signature')!.textContent = text;
};
const setName = (text: string): void => {
document.querySelector('#observableWalletName')!.textContent = text;
};
const clearWalletValues = (): void => {
setName('-');
setAddress('-');
setBalance('-');
setSignature('-');
};
const destroyWallet = async (): Promise<void> => {
await walletManager.destroy();
clearWalletValues();
};
const deactivateWallet = async (): Promise<void> => {
await walletManager.deactivate();
clearWalletValues();
};
const walletManager = new WalletManagerUi({ walletName }, { logger, runtime });
// Wallet object does not change when wallets are activated/deactivated.
// Instead, it's observable properties emit from the currently active wallet.
const wallet = walletManager.wallet;
// Wallet can be subscribed can be used even before it is actually created.
wallet.addresses$.subscribe(([{ address }]) => setAddress(address.toString()));
wallet.balance.utxo.available$.subscribe(({ coins }) => setBalance(coins.toString()));
const createWallet = async (accountIndex: number) => {
clearWalletValues();
// setupWallet call is required to provide context (InputResolver) to the key agent
const { keyAgent } = await setupWallet({
createKeyAgent: async (dependencies) =>
(
await keyManagementFactory.create(
env.KEY_MANAGEMENT_PROVIDER,
{
...env.KEY_MANAGEMENT_PARAMS,
accountIndex
},
logger
)
)(dependencies),
createWallet: async () => wallet,
cryptoProvider: await cryptoProviderFactory.create(env.KEY_MANAGEMENT_PARAMS.cryptoProvider, null, logger),
logger
});
await walletManager.destroy();
await walletManager.activate({ keyAgent, observableWalletName: getObservableWalletName(accountIndex) });
// Same wallet object will return different names, based on which wallet is active
// Calling this method before any wallet is active, will resolve only once a wallet becomes active
setName(await wallet.getName());
};
document.querySelector('#activateWallet1')!.addEventListener('click', async () => await createWallet(0));
document.querySelector('#activateWallet2')!.addEventListener('click', async () => await createWallet(1));
document.querySelector('#deactivateWallet')!.addEventListener('click', async () => await deactivateWallet());
document.querySelector('#destroyWallet')!.addEventListener('click', async () => await destroyWallet());
document.querySelector('#buildAndSignTx')!.addEventListener('click', async () => {
const [{ address: ownAddress }] = await firstValueFrom(wallet.addresses$);
const tx = await wallet.initializeTx({
outputs: new Set<Cardano.TxOut>([
{
address: ownAddress,
value: { coins: 2_000_000n }
}
])
});
const signedTx = await wallet.finalizeTx({ tx });
setSignature(signedTx.witness.signatures.values().next().value);
});