-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.html
373 lines (331 loc) · 16.5 KB
/
index.html
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Elven.js - custom browser only JavaScript SDK for MultiversX blockchain</title>
<meta name="description"
content="Authenticate, sign and send transactions and messages on the MultiversX blockchain in the browser. No need for bundlers, frameworks, etc. Just attach the script source, and you are ready to go.">
<meta property="og:type" content="website" />
<meta property="og:title" content="Elven.js - custom browser only JavaScript SDK for MultiversX blockchain" />
<meta property="og:description"
content="Authenticate, sign and send transactions and messages on the MultiversX blockchain in the browser. No need for bundlers, frameworks, etc. Just attach the script source, and you are ready to go." />
<meta property="og:image" content="" />
<meta property="og:url" content="https://elvenjs.netlify.app/" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Elven.js - custom browser only JavaScript SDK for MultiversX blockchain" />
<meta name="twitter:description"
content="Authenticate, sign and send transactions and messages on the MultiversX blockchain in the browser. No need for bundlers, frameworks, etc. Just attach the script source, and you are ready to go." />
<meta name="twitter:url" content="https://elvenjs.netlify.app/" />
<meta name="twitter:image" content="" />
<link href="demo-styles.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<div class="header" id="header">
<button class="button" id="button-tx" style="display: none;">EGLD transaction</button>
<button class="button" id="button-tx-esdt" style="display: none;">ESDT transaction*</button>
<button class="button" id="button-mint" style="display: none;">Mint NFT</button>
<button class="button" id="button-query" style="display: none;">Query SC**</button>
<button class="button" id="button-login-extension" style="display: block;">Login with Extension</button>
<button class="button" id="button-login-mobile" style="display: block;">Login
with xPortal</button>
<button class="button" id="button-login-web" style="display: block;">Login
with Web Wallet</button>
<button class="button" id="button-login-x-alias" style="display: block;">Login
with xAlias</button>
<button class="button" id="button-logout" style="display: none;">Logout</button>
<a class="button right" href="https://github.com/elven-js/elven.js" target="_blank"
rel="noopener noreferrer">GitHub</a>
</div>
<div class="loader-wrapper">
<div class="loader">Loading...</div>
</div>
<div class="esdt-info">* For the ESDT transfer you will need to get the <a
href="https://devnet-explorer.multiversx.com/tokens/BUILDO-890d14" target="_blank"
rel="noopener noreferrer">BUILDO-890d14</a> token from the faucet: <a
href="https://devnet-multiversx-esdt-faucet.netlify.app/" target="_blank"
rel="noopener noreferrer">https://devnet-multiversx-esdt-faucet.netlify.app</a> (you can also modify the
hardcoded
token and test it with yours locally, check the sourcecode of this website for more info).</div>
<div class="esdt-info">** The query will trigger a 'getMintedPerAddressTotal' with currently logged in user's
address using
the <a href="https://www.elven.tools">Elven Tools</a> Smart Contract.</div>
<div id="tx-hash-or-query-result" class="tx-hash-or-query-result"></div>
<div id="qr-code-container" class="qr-code-container"></div>
<h1>ElvenJS (demo)</h1>
<div><strong>All transactions will take place on the devent!</strong> Check how to use it on the testnet and mainnet
in the docs.</div>
<h4>Docs and code: <a href="https://www.elvenjs.com">www.elvenjs.com</a></h4>
<h5>For styling elements like QR code container and Wallet Connect pairings check <a
href="https://github.com/elven-js/elven.js/blob/main/example/demo-styles.css">demo styles</a>. Each element
should have a class name.</h5>
<h5>Remember to change <i>walletConnectV2ProjectId</i>. You can get yours here <a
href="https://cloud.walletconnect.com/sign-in">https://cloud.walletconnect.com/sign-in</a> </h5>
<p>Authenticate, sign and send transactions and messages on the MultiversX blockchain in the browser. No need for
bundlers, frameworks, etc. Just attach the script source, and you are ready to go. You can incorporate it into
your preferred CMS framework like WordPress or an e-commerce system. Plus, it will also work on a standard static
HTML website.</p>
<p>For now, xPortal mobile app, Web Wallet and MultiversX browser extension are supported. Check GitHub for more
info!</p>
<p>The primary purpose of this tool is to have a lite script for browser usage where you can authenticate and
sign/send transactions on the MultiversX blockchain and do this without any additional build steps.</p>
<p>The purpose is to simplify the usage for primary use cases and open the doors for many frontend tools and
approaches.</p>
<p>The demo here presents the full path of initialization, logging in, and sending a
transaction.</p>
<p>
It is a script for browsers that incorporates ES6 modules. If you need fully functional
JavaScript/Typescript SDK (also in Nodejs), please use <a href="https://github.com/multiversx/mx-sdk-js-core"
target="_blank" rel="noopener noreferrer">sdk-js</a>, an official Typescript MultiversX SDK.
</p>
<h4>Soon there will be more docs and examples!</h4>
<h4>Check the source code of this page to get the complete code. All is static. The main script is
minified. But you can see the code in the <a href="https://github.com/elven-js/elven.js" target="_blank"
rel="noopener noreferrer">repository</a></h4>
<h3>Demo transactions/queries description (devnet):</h3>
<div>EGLD transaction:</div>
<ul>
<li>simple EGLD transfer on the devnet chain</li>
<li>it will go to a predefined wallet</li>
<li>the value will be 0,001 EGLD</li>
<li>after the transaction is finished below, you will find the transaction hash</li>
</ul>
<div>ESDT transaction:</div>
<ul>
<li>simple ESDT transfer on the devnet chain</li>
<li>it will go to a predefined wallet</li>
<li>it will be 1 BUILDO-890d14 token</li>
<li>after the transaction is finished below, you will find the transaction hash</li>
</ul>
<div>Mint transaction:</div>
<ul>
<li>Smart Contract call on the devnet chain</li>
<li>it will call predefined smart contract (Elven Tools Smart Contract) and mint NFT</li>
<li>after the transaction is finished below, you will find the transaction hash</li>
</ul>
<div>Query the smart contract:</div>
<ul>
<li>Smart Contract query. The Elven Tools smart contract has the 'getMintedPerAddressTotal' function</li>
<li>It will query using a predefined address and return the value</li>
<li>There is a custom logic for results decoding. In the future there will be tools for that</li>
<li>after the transaction is finished below, you will get the result of the query</li>
</ul>
<h3>Other demos:</h3>
<ol>
<li><a href="https://stackblitz.com/edit/web-platform-d4rx5v?file=index.html" target="_blank"
rel="noopener noreferrer">StackBlitz vanilla html demo</a></li>
<li><a href="https://stackblitz.com/edit/vitejs-vite-rbo6du?file=src/App.tsx" target="_blank"
rel="noopener noreferrer">StackBlitz Solid.js demo</a></li>
<li><a href="https://stackblitz.com/edit/vitejs-vite-qr2u7l?file=src/App.tsx" target="_blank"
rel="noopener noreferrer">StackBlitz React demo</a></li>
<li><a href="https://stackblitz.com/edit/vue-zrb8y5?file=src/App.vue" target="_blank"
rel="noopener noreferrer">StackBlitz Vue demo</a></li>
</ol>
</div>
<script type="module">
// Just for the demo
import {
uiLoggedInState,
uiPending,
updateTxHashContainer,
base64ToDecimalHex,
updateQueryResultContainer,
clearQrCodeContainer
} from './demo-ui-tools.js'
// Elven.js tools
import {
ElvenJS,
Transaction,
Address,
TransactionPayload,
TokenTransfer,
TransferTransactionsFactory,
U32Value,
AddressValue,
SmartContract,
GasEstimator,
ContractFunction
} from './elven.js';
// Options are the defaults and here only to show all of them
// You don't have to add them if you want to use default setup
// You can only add your custom callbacks
const initElven = async () => {
await ElvenJS.init(
{
apiUrl: 'https://devnet-api.multiversx.com',
chainType: 'devnet',
apiTimeout: 10000,
// Remember to change it. Get yours here: https://cloud.walletconnect.com/sign-in
walletConnectV2ProjectId: 'f502675c63610bfe4454080ac86d70e6',
walletConnectV2RelayAddresses: ['wss://relay.walletconnect.com'],
onLoginPending: () => { uiPending(true) },
onLoggedIn: () => { uiLoggedInState(true); uiPending(false); },
onLogout: () => { uiLoggedInState(false); },
onTxStarted: (tx) => { uiPending(true); },
onTxSent: (tx) => { console.log('Tx sent, not finalized on chain yet! ', tx.getHash().toString()) },
onTxFinalized: (tx) => { tx?.hash && updateTxHashContainer(tx.hash); uiPending(false); },
onTxError: (tx, error) => { console.log('Tx error: ', error); uiPending(false); },
onQrPending: () => { uiPending(true); },
onQrLoaded: () => { uiPending(false); },
}
);
}
initElven();
document.getElementById('button-login-extension').addEventListener('click', async () => {
try {
clearQrCodeContainer();
await ElvenJS.login('browser-extension');
} catch (e) {
console.log('Login: Something went wrong, try again!', e?.message);
}
});
document.getElementById('button-login-mobile').addEventListener('click', async () => {
clearQrCodeContainer();
try {
await ElvenJS.login('mobile', {
// You can also use the DOM element here:
// qrCodeContainer: document.querySelector('#qr-code-container')
qrCodeContainer: 'qr-code-container',
});
} catch (e) {
console.log('Login: Something went wrong, try again!', e?.message);
}
});
document.getElementById('button-login-web').addEventListener('click', async () => {
try {
clearQrCodeContainer();
await ElvenJS.login('web-wallet', {
callbackRoute: '/',
});
} catch (e) {
console.log('Login: Something went wrong, try again!', e?.message);
}
});
document.getElementById('button-login-x-alias').addEventListener('click', async () => {
try {
clearQrCodeContainer();
await ElvenJS.login('x-alias', {
callbackRoute: '/',
});
} catch (e) {
console.log('Login: Something went wrong, try again!', e?.message);
}
});
document.getElementById('button-logout').addEventListener('click', async () => {
try {
const isLoggedOut = await ElvenJS.logout();
} catch (e) {
console.error(e.message);
}
});
// Simple EGLD transfer transaction
const egldTransferAddress = 'erd17a4wydhhd6t3hhssvcp9g23ppn7lgkk4g2tww3eqzx4mlq95dukss0g50f';
document.getElementById('button-tx').addEventListener('click', async () => {
updateTxHashContainer(false);
const demoMessage = 'Transaction demo from Elven.js!';
const isGuardian = ElvenJS.storage.get('activeGuardian');
const isXalias = ElvenJS.storage.get('loginMethod') === 'x-alias';
// Additional 50000 when there is an active guardian
// See more about gas limit calculation here: https://docs.multiversx.com/developers/gas-and-fees/overview/
const gasLimit = ((isGuardian || isXalias) ? 100000 : 50000) + 1500 * demoMessage.length;
const tx = new Transaction({
nonce: ElvenJS.storage.get('nonce'),
receiver: new Address(egldTransferAddress),
gasLimit,
chainID: 'D',
data: new TransactionPayload(demoMessage),
value: TokenTransfer.egldFromAmount(0.001),
sender: new Address(ElvenJS.storage.get('address')),
});
try {
await ElvenJS.signAndSendTransaction(tx);
} catch (e) {
throw new Error(e?.message);
}
});
// Simple ESDT transfer transaction
const esdtTransferAddress = 'erd17a4wydhhd6t3hhssvcp9g23ppn7lgkk4g2tww3eqzx4mlq95dukss0g50f';
document.getElementById('button-tx-esdt').addEventListener('click', async () => {
updateTxHashContainer(false);
// The preconfigured transaction is for the 1 'BUILDO-890d14' ESDT token on the devnet
// You need to know its ticker and how many decimals places it has
// In this case, the token has 18 decimal places. You can check it in the MultiversX devnet explorer
// You can use the community-based faucet to get the BUILDO-890d14 token: https://r3d4.fr/faucet
const transfer = TokenTransfer.fungibleFromAmount(
'BUILDO-890d14',
'1',
18
);
const factory = new TransferTransactionsFactory(new GasEstimator());
const tx = factory.createESDTTransfer({
tokenTransfer: transfer,
receiver: new Address(esdtTransferAddress),
sender: new Address(ElvenJS.storage.get('address')),
chainID: 'D',
});
try {
await ElvenJS.signAndSendTransaction(tx);
} catch (e) {
throw new Error(e?.message);
}
});
// Mint nft function
// It mints on the smart contract from: https://dapp-demo.elven.tools/
const nftMinterSmartContract = 'erd1qqqqqqqqqqqqqpgqztp5vpqrxe2tha224jwsa3sv2800a88zgtksar2kc8';
document.getElementById('button-mint').addEventListener('click', async () => {
updateTxHashContainer(false);
const contractAddress = new Address(nftMinterSmartContract);
const contract = new SmartContract({ address: contractAddress });
const isGuardian = ElvenJS.storage.get('activeGuardian');
// Additional 50000 when there is an active guardian
// See more about gas limit calculation here: https://docs.multiversx.com/developers/gas-and-fees/overview/
const gasLimit = isGuardian ? 14050000 : 14000000;
const tx = contract.call({
caller: new Address(ElvenJS.storage.get('address')),
value: TokenTransfer.egldFromAmount(0.01),
func: new ContractFunction("mint"),
gasLimit,
args: [new U32Value(1)],
chainID: "D"
})
try {
await ElvenJS.signAndSendTransaction(tx);
} catch (e) {
throw new Error(e?.message);
}
});
// Query the smart contract. It will query the same smart contract as for minting
// It will check how many tokens a particular address has minted already (the function name: getMintedPerAddressTotal)
// The function takes the address as argument
// The results have to be parsed. The result parser tool and abi registry will land in a separate library
// You can still decode simple types like numbers, boolean, and strings without them (example below)
// Read more about the Elven Tools Smart Contract here: https://www.elven.tools/docs/sc-endpoints.html
document.getElementById('button-query').addEventListener('click', async () => {
try {
updateQueryResultContainer();
uiPending(true);
const results = await ElvenJS.queryContract({
address: new Address(nftMinterSmartContract),
func: new ContractFunction('getMintedPerAddressTotal'),
args: [new AddressValue(new Address(ElvenJS.storage.get('address')))]
});
uiPending(false);
// Manual decoding of a simple type (number here), there will be additional tools for that
// For more possibilities, for now please check data converter in Buildo CLI:
// https://github.com/xdevguild/buildo-begins/blob/main/src/converters.ts
const hexVal = base64ToDecimalHex(results?.returnData?.[0]);
let intVal = 0;
if (hexVal) {
intVal = parseInt(hexVal, 16);
}
updateQueryResultContainer(`➡️ The result of the query is: ${intVal}`);
} catch (e) {
uiPending(false);
throw new Error(e?.message);
}
});
</script>
</body>
</html>