Skip to content

Commit 6caf0ab

Browse files
authored
Merge pull request #641 from Concordium/fix-rust-bindings-4
WIP: Fix browser specific imports for the rust-bindings library.
2 parents fc47aeb + f6759dd commit 6caf0ab

9 files changed

Lines changed: 235 additions & 28 deletions

File tree

examples/web-simple/index.html

Lines changed: 145 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,150 @@
11
<!doctype html>
22
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Concordium SDK - Web UMD Test</title>
6+
<script src="../../node_modules/@concordium/web-sdk/lib/min/concordium.web.min.js"></script>
7+
<style>
8+
body {
9+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
10+
max-width: 800px;
11+
margin: 40px auto;
12+
padding: 0 20px;
13+
line-height: 1.6;
14+
}
15+
h1 {
16+
border-bottom: 2px solid #eee;
17+
padding-bottom: 10px;
18+
}
19+
.test {
20+
padding: 10px;
21+
margin: 8px 0;
22+
border-radius: 4px;
23+
border-left: 4px solid;
24+
}
25+
.test.pass {
26+
background: #f0fff0;
27+
border-color: #2e7d32;
28+
}
29+
.test.fail {
30+
background: #fff0f0;
31+
border-color: #c62828;
32+
}
33+
.test-name {
34+
font-weight: 600;
35+
}
36+
.test-result {
37+
font-family: monospace;
38+
font-size: 12px;
39+
color: #666;
40+
margin-top: 4px;
41+
word-break: break-all;
42+
}
43+
.status {
44+
font-weight: bold;
45+
}
46+
.status.pass {
47+
color: #2e7d32;
48+
}
49+
.status.fail {
50+
color: #c62828;
51+
}
52+
#summary {
53+
margin-top: 20px;
54+
padding: 15px;
55+
background: #f5f5f5;
56+
border-radius: 4px;
57+
font-weight: 600;
58+
}
59+
</style>
60+
</head>
361

4-
<head>
5-
<meta charset="utf-8" />
6-
<script src="../../node_modules/@concordium/web-sdk/lib/min/concordium.web.min.js"></script>
7-
</head>
8-
9-
<body>
10-
<div id="root"></div>
11-
<script>
12-
// Verifies that PLT works in UMD.
13-
const account = concordiumSDK.AccountAddress.fromBase58('4UC8o4m8AgTxt5VBFMdLwMCwwJQVJwjesNzW7RPXkACynrULmd');
14-
const tokenAmount = concordiumSDK.TokenAmount.create(100, 2);
15-
console.log(account, tokenAmount);
16-
17-
// Verifies that UMD wasm functions work
18-
const schema = concordiumSDK.toBuffer('FAACAAAABAAAAGtleXMQAR4gAAAADgAAAGF1eGlsaWFyeV9kYXRhEAEC', 'base64');
19-
console.log(concordiumSDK.displayTypeSchemaTemplate(schema));
20-
</script>
21-
</body>
62+
<body>
63+
<h1>Concordium SDK - Web UMD Test</h1>
64+
<div id="results"></div>
65+
<div id="summary"></div>
2266

67+
<script>
68+
const results = document.getElementById('results');
69+
const summary = document.getElementById('summary');
70+
let passed = 0,
71+
failed = 0;
72+
73+
function test(name, fn) {
74+
const div = document.createElement('div');
75+
div.className = 'test';
76+
try {
77+
const result = fn();
78+
div.className += ' pass';
79+
div.innerHTML = `<span class="status pass">✓ PASS</span> <span class="test-name">${name}</span>`;
80+
if (result !== undefined) {
81+
div.innerHTML += `<div class="test-result">${escapeHtml(String(result))}</div>`;
82+
}
83+
passed++;
84+
} catch (e) {
85+
div.className += ' fail';
86+
div.innerHTML = `<span class="status fail">✗ FAIL</span> <span class="test-name">${name}</span>`;
87+
div.innerHTML += `<div class="test-result">${escapeHtml(e.message)}</div>`;
88+
failed++;
89+
}
90+
results.appendChild(div);
91+
}
92+
93+
function escapeHtml(str) {
94+
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
95+
}
96+
97+
// Test: AccountAddress.fromBase58
98+
test('AccountAddress.fromBase58()', () => {
99+
const account = concordiumSDK.AccountAddress.fromBase58(
100+
'4UC8o4m8AgTxt5VBFMdLwMCwwJQVJwjesNzW7RPXkACynrULmd'
101+
);
102+
return account.address;
103+
});
104+
105+
// Test: TokenAmount.create (PLT functionality)
106+
test('TokenAmount.create() - PLT functionality', () => {
107+
const tokenAmount = concordiumSDK.TokenAmount.create(100, 2);
108+
return `TokenAmount: ${tokenAmount.toString()}`;
109+
});
110+
111+
// Test: displayTypeSchemaTemplate (WASM functionality)
112+
test('displayTypeSchemaTemplate() - WASM functionality', () => {
113+
const schema = concordiumSDK.toBuffer(
114+
'FAACAAAABAAAAGtleXMQAR4gAAAADgAAAGF1eGlsaWFyeV9kYXRhEAEC',
115+
'base64'
116+
);
117+
const template = concordiumSDK.displayTypeSchemaTemplate(schema);
118+
return template.substring(0, 100) + (template.length > 100 ? '...' : '');
119+
});
120+
121+
// Test: ConcordiumGRPCWebClient exists
122+
test('ConcordiumGRPCWebClient available', () => {
123+
if (typeof concordiumSDK.ConcordiumGRPCWebClient !== 'function') {
124+
throw new Error('ConcordiumGRPCWebClient is not a function');
125+
}
126+
return 'Constructor available';
127+
});
128+
129+
// Test: generateBakerKeys (WASM - wallet module)
130+
test('generateBakerKeys() - WASM wallet module', () => {
131+
const account = concordiumSDK.AccountAddress.fromBase58(
132+
'4UC8o4m8AgTxt5VBFMdLwMCwwJQVJwjesNzW7RPXkACynrULmd'
133+
);
134+
const keys = concordiumSDK.generateBakerKeys(account);
135+
if (!keys.electionVerifyKey || !keys.signatureVerifyKey || !keys.aggregationVerifyKey) {
136+
throw new Error('Missing expected keys in result');
137+
}
138+
return `electionVerifyKey: ${keys.electionVerifyKey.substring(0, 20)}...`;
139+
});
140+
141+
// Display summary
142+
const total = passed + failed;
143+
summary.innerHTML =
144+
`Tests: ${passed}/${total} passed` +
145+
(failed > 0
146+
? ` <span style="color: #c62828">(${failed} failed)</span>`
147+
: ' <span style="color: #2e7d32">✓</span>');
148+
</script>
149+
</body>
23150
</html>

packages/rust-bindings/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## Unreleased
44

5+
## 4.0.1
6+
7+
### Fixed
8+
9+
- An issue where the browser entrypoints of the package did not work.
10+
511
## 4.0.0
612

713
### Breaking changes

packages/rust-bindings/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/rust-bindings/package.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@concordium/rust-bindings",
3-
"version": "4.0.0",
3+
"version": "4.0.1",
44
"license": "Apache-2.0",
55
"type": "module",
66
"engines": {
@@ -28,8 +28,9 @@
2828
"default": "./lib/dapp/node/cjs/index.cjs"
2929
},
3030
"browser": {
31+
"module": "./lib/dapp/web/esm/index.min.js",
3132
"types": "./lib/dapp/web/esm/index.d.ts",
32-
"import": "./lib/dapp/web/esm/index.js",
33+
"import": "./lib/dapp/web/esm/index.min.js",
3334
"default": "./lib/dapp/web/umd/index.min.js"
3435
},
3536
"default": "./lib/dapp/web/umd/index.min.js"
@@ -41,8 +42,9 @@
4142
"default": "./lib/dapp/node/cjs/index.cjs"
4243
},
4344
"browser": {
45+
"module": "./lib/dapp/web/esm/index.min.js",
4446
"types": "./lib/dapp/web/esm/index.d.ts",
45-
"import": "./lib/dapp/web/esm/index.js",
47+
"import": "./lib/dapp/web/esm/index.min.js",
4648
"default": "./lib/dapp/web/umd/index.min.js"
4749
},
4850
"default": "./lib/dapp/web/umd/index.min.js"
@@ -54,8 +56,9 @@
5456
"default": "./lib/wallet/node/cjs/index.cjs"
5557
},
5658
"browser": {
59+
"module": "./lib/wallet/web/esm/index.min.js",
5760
"types": "./lib/wallet/web/esm/index.d.ts",
58-
"import": "./lib/wallet/web/esm/index.js",
61+
"import": "./lib/wallet/web/esm/index.min.js",
5962
"default": "./lib/wallet/web/umd/index.min.js"
6063
},
6164
"default": "./lib/wallet/web/umd/index.min.js"
@@ -79,7 +82,7 @@
7982
"scripts": {
8083
"rustfmt": "cargo +nightly-2023-04-01-x86_64-unknown-linux-gnu fmt -- --color=always",
8184
"clippy": "cargo +1.73 clippy --color=always --tests --benches -- -Dclippy::all",
82-
"build-web": "wasm-pack build ./packages/$0 --target web --out-dir $INIT_CWD/lib/$0/web/esm --out-name index",
85+
"build-web": "wasm-pack build ./packages/$0 --target web --out-dir $INIT_CWD/lib/$0/web/esm --out-name index && tsx ./scripts/web-esm-remove-init.ts $0",
8386
"build-node": "wasm-pack build ./packages/$0 --target nodejs --out-dir $INIT_CWD/lib/$0/node/cjs --out-name index && tsx ./scripts/fix-nodejs-ext.ts",
8487
"build-bundler": "wasm-pack build ./packages/$0 --target bundler --out-dir $INIT_CWD/lib/$0/bundler --out-name index",
8588
"build-all": "yarn build-web $0 && yarn build-node $0 && yarn build-bundler $0",
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import * as fs from 'fs';
2+
import { fileURLToPath } from 'node:url';
3+
import * as path from 'path';
4+
5+
/**
6+
* The point of this script is to convert the ESM produced by wasm-pack to something that can be compiled by bundlers.
7+
*
8+
* The error happening when _not_ running the script is related to the `new URL('index_bg.wasm', import.meta.url)`, as
9+
* bundlers will try to read the file at the location. The function this code snippet is embedded in, is not used in the
10+
* format exposed by the rust-bindings library.
11+
*/
12+
13+
const name = process.argv[2];
14+
if (!name) {
15+
console.error('Usage: tsx scripts/web-esm-remove-init.ts <name>');
16+
process.exit(1);
17+
}
18+
19+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
20+
const filePath = path.resolve(__dirname, '..', `lib/${name}/web/esm/index.js`);
21+
22+
if (!fs.existsSync(filePath)) {
23+
console.warn(`${filePath} not found.`);
24+
process.exit(0);
25+
}
26+
const content = fs.readFileSync(filePath, 'utf8');
27+
const updated = content.replace("module_or_path = new URL('index_bg.wasm', import.meta.url);", '');
28+
if (updated !== content) {
29+
fs.writeFileSync(filePath, updated);
30+
} else {
31+
console.warn(`No line to remove in ${filePath}`);
32+
}

packages/rust-bindings/webpack.config.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ type WebpackEnv = Partial<{
99
package: string;
1010
}>;
1111

12-
function configFor(target: 'web' | 'node', pkg?: string): Configuration {
12+
function configFor(target: 'web' | 'node', output: 'umd' | 'esm', pkg?: string): Configuration {
1313
const config: Configuration = {
1414
mode: 'production',
1515
cache: {
@@ -52,6 +52,32 @@ function configFor(target: 'web' | 'node', pkg?: string): Configuration {
5252
},
5353
};
5454

55+
switch (output) {
56+
case 'umd': {
57+
config.output = {
58+
filename: `[name]/${target}/umd/index.min.js`,
59+
path: resolve(__dirname, 'lib'),
60+
library: { type: 'umd' },
61+
publicPath: '',
62+
};
63+
break;
64+
}
65+
case 'esm': {
66+
config.output = {
67+
module: true,
68+
filename: `[name]/${target}/esm/index.min.js`,
69+
path: resolve(__dirname, 'lib'),
70+
library: { type: 'module' },
71+
};
72+
config.experiments = {
73+
outputModule: true,
74+
};
75+
break;
76+
}
77+
default:
78+
throw new Error('Unsupported output');
79+
}
80+
5581
if (!pkg) {
5682
config.entry = {
5783
dapp: resolve(__dirname, './ts-src/dapp.ts'),
@@ -66,4 +92,8 @@ function configFor(target: 'web' | 'node', pkg?: string): Configuration {
6692
return config;
6793
}
6894

69-
export default (env: WebpackEnv) => [configFor('web', env.package), configFor('node', env.package)];
95+
export default (env: WebpackEnv) => [
96+
configFor('web', 'umd', env.package),
97+
configFor('node', 'umd', env.package),
98+
configFor('web', 'esm', env.package),
99+
];

packages/sdk/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
## Unreleased
44

5+
## 11.1.1
6+
7+
### Fixed
8+
9+
- An issue where WASM functionality could not be used when using the browser UMD library, orin a web context
10+
without applying the bundler optimization.
11+
512
## 11.1.0
613

714
### Added

packages/sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@concordium/web-sdk",
3-
"version": "11.1.0",
3+
"version": "11.1.1",
44
"license": "Apache-2.0",
55
"engines": {
66
"node": ">=16"

packages/sdk/webpack.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ function configFor(target: 'web' | 'node' | 'react-native'): webpack.Configurati
3636
},
3737
},
3838
module: {
39+
// Don't parse the rust-bindings UMD bundles - they are self-contained with WASM initialization
40+
noParse: /rust-bindings\/lib\/.*\/umd\/index\.min\.js$/,
3941
rules: [
4042
{
4143
test: /\.tsx?$/,

0 commit comments

Comments
 (0)