create-leo-app 0.8.2 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-leo-app",
3
- "version": "0.8.2",
3
+ "version": "0.8.6",
4
4
  "type": "module",
5
5
  "license": "GPL-3.0",
6
6
  "collaborators": [
@@ -13,7 +13,7 @@ async function createOffscreen(path) {
13
13
  await chrome.offscreen.createDocument({
14
14
  url: offscreenUrl,
15
15
  reasons: ["WORKERS"],
16
- justification: "Top-level await and Workers cannot be used in service workers, but they are necessary to use the Aleo SDK.",
16
+ justification: "Top-level await and Workers cannot be used in service workers, but they are necessary to use the Provable SDK.",
17
17
  });
18
18
  }
19
19
 
@@ -1,9 +1,9 @@
1
1
  # Offline Transaction Builder
2
2
 
3
3
  ## 1. Overview
4
- ### 1.1 Proving Keys for Zero Knowledge Function Execution
5
- To achieve zero knowledge execution, all Aleo functions require a `ProvingKey` and `VerifyingKey` in order to build a
6
- zero knowledge ZkSnark proof of execution. If a user does not possess these keys for a function, they are normally
4
+ ### 1.1 Proving Keys for Zero-Knowledge Function Execution
5
+ To achieve zero-knowledge execution, all Aleo functions require a `ProvingKey` and `VerifyingKey` in order to build a
6
+ zero-knowledge zk-SNARK proof of execution. If a user does not possess these keys for a function, they are normally
7
7
  downloaded from the internet when the function is called.
8
8
 
9
9
  ### 1.2 Key Providers
@@ -21,31 +21,27 @@ the internet for it. This provides a way to build Aleo execution transactions wi
21
21
  This pathway is suitable for use-cases such as hardware wallets or air-gapped machines used
22
22
  for building secure transactions.
23
23
 
24
- ### 1.4 Assumptions
24
+ ### 1.4 Transaction Types
25
25
 
26
- The key material in this example is assumed to be pre-downloaded onto the machine performing the
27
- construction of the offline transaction.
26
+ Several types of transactions can be built and executed using this template:
27
+
28
+ `bond_public`
29
+ `unbond_public`
30
+ `claim_unbond_public`
28
31
 
29
32
  ## 2. Usage
30
33
 
31
- ### 2.1 Pre-Download the Keys
32
- First run this command online to download the key material to disk:
34
+ `npm run build`
33
35
 
34
- `npm start`
36
+ `npm run dev`
35
37
 
36
38
  Once this command is run, all proving keys for the `transfer_public`, `bond_public`, `unbond_public`, and
37
- `claim_unbond_public` functions will be downloaded to the `./keys` folder. The machine can then be disconnected from
39
+ `claim_unbond_public` functions will be downloaded to the `dist/keys` folder. The machine can then be disconnected from
38
40
  the internet and the `OfflineKeyProvider` will search this directory for the function proving keys when building the
39
41
  transaction instead of connecting to the internet. Alternatively you can skip the online step entirely by adding the proving key creating this directory manually and
40
42
  adding the key material yourself.
41
43
 
42
- ### 2.2 Build the Transaction Offline
43
-
44
- Once the key material is downloaded, turn off your internet connection and run the following command:
45
-
46
- `npm start`
47
-
48
- You should see the transactions being built and the resulting transaction IDs printed to the console.
44
+ Once the keys are downloaded to your local machine, the offline transactions will be built without requiring an internet connection.
49
45
 
50
46
  ## 3. Notes
51
47
 
@@ -28,7 +28,7 @@ async function preDownloadTransferKeys() {
28
28
  const keysDirPath = path.join(__dirname, "keys");
29
29
  await fsPromises.mkdir(keysDirPath, { recursive: true });
30
30
 
31
- for (const keyData of [CREDITS_PROGRAM_KEYS.transfer_public, CREDITS_PROGRAM_KEYS.fee_public]) {
31
+ for (const keyData of [CREDITS_PROGRAM_KEYS.transfer_public, CREDITS_PROGRAM_KEYS.fee_public, CREDITS_PROGRAM_KEYS.transfer_public_as_signer]) {
32
32
  try {
33
33
  keyPaths[keyData.locator] = await downloadAndSaveKey(keyData, keysDirPath);
34
34
  } catch (error) {
@@ -15,10 +15,11 @@ async function buildTransferPublicTxOffline(recipientAddress: Address, amount: n
15
15
  // Create the proving keys from the key bytes on the offline machine
16
16
  console.log("Creating proving keys from local key files");
17
17
  const feePublicKeyBytes = await getLocalKey(<string>keyPaths[CREDITS_PROGRAM_KEYS.fee_public.locator]);
18
- const transferPublicAsSignerKeyBytes = await getLocalKey(<string>keyPaths[CREDITS_PROGRAM_KEYS.transfer_public_as_signer.locator]);
19
18
  const feePublicProvingKey = ProvingKey.fromBytes(feePublicKeyBytes);
20
- const transferPublicProvingKey = ProvingKey.fromBytes(transferPublicAsSignerKeyBytes);
21
-
19
+ const transferPublicProvingKey = ProvingKey.fromBytes(
20
+ await getLocalKey(<string>keyPaths[CREDITS_PROGRAM_KEYS.transfer_public.locator])
21
+ );
22
+
22
23
  // Create an offline key provider
23
24
  console.log("Creating offline key provider");
24
25
  const offlineKeyProvider = new OfflineKeyProvider();
@@ -27,10 +28,25 @@ async function buildTransferPublicTxOffline(recipientAddress: Address, amount: n
27
28
  // keys into the key manager.
28
29
  console.log("Inserting proving keys into key provider");
29
30
  offlineKeyProvider.insertFeePublicKeys(feePublicProvingKey);
31
+
32
+ try {
30
33
  offlineKeyProvider.insertTransferPublicKeys(transferPublicProvingKey);
34
+ console.log("Successfully inserted proving key");
35
+ } catch (err) {
36
+ console.error("Failed to insert proving key:", err);
37
+ }
38
+
31
39
 
32
40
  // Create an offline query to complete the inclusion proof
33
- const offlineQuery = new OfflineQuery(latestStateRoot);
41
+ let offlineQuery: OfflineQuery;
42
+ const blockHeight = 0;
43
+ // TODO this is a placeholder block height for now, which offlineQuery now requires
44
+ try {
45
+ const offlineQuery = new OfflineQuery(blockHeight, latestStateRoot);
46
+ console.log("Successfully created OfflineQuery", offlineQuery);
47
+ } catch (err) {
48
+ console.error("Failed to create OfflineQuery:", err);
49
+ }
34
50
 
35
51
  // Insert the key provider into the program manager
36
52
  programManager.setKeyProvider(offlineKeyProvider);
@@ -47,7 +63,13 @@ async function buildTransferPublicTxOffline(recipientAddress: Address, amount: n
47
63
  }
48
64
 
49
65
  /// Build bonding and unbonding transactions without connection to the internet
50
- async function buildBondingTxOffline(stakerAddress: Address, validatorAddress: Address, withdrawalAddress: Address, amount: number, latestStateRoot: string, keyPaths: {}): Promise<Transaction[]> {
66
+ async function buildBondingTxOffline(
67
+ validatorAddress: Address,
68
+ withdrawalAddress: Address,
69
+ amount: number,
70
+ latestStateRoot: string,
71
+ keyPaths: {}
72
+ ): Promise<Transaction[]> {
51
73
  // Create an offline program manager
52
74
  const programManager = new ProgramManager();
53
75
 
@@ -70,8 +92,7 @@ async function buildBondingTxOffline(stakerAddress: Address, validatorAddress:
70
92
  console.log("Creating offline key provider");
71
93
  const offlineKeyProvider = new OfflineKeyProvider();
72
94
 
73
- // Insert the proving keys into the offline key provider. The key provider will automatically insert the verifying
74
- // keys into the key manager.
95
+ // Insert the proving keys into the offline key provider
75
96
  console.log("Inserting proving keys into key provider");
76
97
  offlineKeyProvider.insertFeePublicKeys(feePublicProvingKey);
77
98
  offlineKeyProvider.insertBondPublicKeys(bondPublicProvingKey);
@@ -83,49 +104,48 @@ async function buildBondingTxOffline(stakerAddress: Address, validatorAddress:
83
104
 
84
105
  // Build the bonding transactions offline
85
106
  console.log("Building a bond_public execution transaction offline");
86
- const bondPublicOptions = {
87
- executionParams: {
88
- keySearchParams: OfflineSearchParams.bondPublicKeyParams()
89
- },
90
- offlineParams: {
91
- offlineQuery: new OfflineQuery(latestStateRoot)
92
- }
107
+
108
+ if (!latestStateRoot) {
109
+ throw new Error("latestStateRoot is undefined");
93
110
  }
94
111
 
112
+ const bondPublicOptions = {
113
+ keySearchParams: OfflineSearchParams.bondPublicKeyParams(),
114
+ offlineQuery: new OfflineQuery(0, latestStateRoot)
115
+ };
116
+
117
+
95
118
  const bondTx = <Transaction>await programManager.buildBondPublicTransaction(
96
- stakerAddress.to_string(),
97
119
  validatorAddress.to_string(),
98
120
  withdrawalAddress.to_string(),
99
121
  amount,
100
- bondPublicOptions,
101
- )
122
+ bondPublicOptions
123
+ );
124
+
102
125
  console.log("\nbond_public transaction built!\n");
103
126
 
104
- console.log("Building an unbond_public execution transaction offline")
105
127
  const unbondPublicOptions = {
106
- executionParams: {
107
- keySearchParams: OfflineSearchParams.unbondPublicKeyParams()
108
- },
109
- offlineParams: {
110
- offlineQuery: new OfflineQuery(latestStateRoot)
111
- }
112
- }
128
+ keySearchParams: OfflineSearchParams.unbondPublicKeyParams(),
129
+ offlineQuery: new OfflineQuery(0, latestStateRoot)
130
+ };
113
131
 
114
- const unBondTx = <Transaction>await programManager.buildUnbondPublicTransaction(stakerAddress.to_string(), amount, unbondPublicOptions);
132
+ const unBondTx = <Transaction>await programManager.buildUnbondPublicTransaction(
133
+ stakerAddress.to_string(),
134
+ amount,
135
+ unbondPublicOptions
136
+ );
115
137
  console.log("\nunbond_public transaction built!\n");
116
138
 
117
- console.log("Building a claim_unbond_public transaction offline")
118
- // Build the claim unbonding transaction offline
139
+ console.log("Building a claim_unbond_public transaction offline");
119
140
  const claimUnbondPublicOptions = {
120
- executionParams: {
121
- keySearchParams: OfflineSearchParams.claimUnbondPublicKeyParams()
122
- },
123
- offlineParams: {
124
- offlineQuery: new OfflineQuery(latestStateRoot)
125
- }
126
- }
141
+ keySearchParams: OfflineSearchParams.claimUnbondPublicKeyParams(),
142
+ offlineQuery: new OfflineQuery(0, latestStateRoot)
143
+ };
127
144
 
128
- const claimUnbondTx = <Transaction>await programManager.buildClaimUnbondPublicTransaction(stakerAddress.to_string(), claimUnbondPublicOptions);
145
+ const claimUnbondTx = <Transaction>await programManager.buildClaimUnbondPublicTransaction(
146
+ stakerAddress.to_string(),
147
+ claimUnbondPublicOptions
148
+ );
129
149
  console.log("\nclaim_unbond_public transaction built!\n");
130
150
  return [bondTx, unBondTx, claimUnbondTx];
131
151
  }
@@ -153,13 +173,13 @@ console.log(`\n---------------transfer_public transaction---------------\n${tran
153
173
  console.log(`---------------------------------------------------------`);
154
174
 
155
175
  // Build bonding & unbonding transactions
156
- const bondTransactions = await buildBondingTxOffline(stakerAddress, validatorAddress, withdrawalAddress, 100, latestStateRoot, bondingKeyPaths);
176
+ const bondTransactions = await buildBondingTxOffline(validatorAddress, withdrawalAddress, 100, latestStateRoot, bondingKeyPaths);
157
177
  console.log("Bonding transactions built offline!");
158
178
  console.log(`\n-----------------bond_public transaction-----------------\n${bondTransactions[0]}`);
159
179
  console.log(`---------------------------------------------------------`);
160
180
  console.log(`\n----------------unbond_public transaction:---------------\n${bondTransactions[1]}`);
161
181
  console.log(`---------------------------------------------------------`);
162
- console.log(`\n-----------------claim_unbond transaction:---------------\n${bondTransactions[2]}`);
182
+ console.log(`\n-----------------claim_unbond_public transaction:---------------\n${bondTransactions[2]}`);
163
183
  console.log(`---------------------------------------------------------`);
164
184
  //---------------------------------------------------------
165
185
 
@@ -168,4 +188,4 @@ console.log(`---------------------------------------------------------`);
168
188
  // ONLINE COMPONENT (Uncomment this part to send the transaction to the Aleo Network on an internet connected machine)
169
189
  // Submit the transaction to the network
170
190
  // const transferTxId = await networkClient.submitTransaction(transferTx);
171
- //---------------------------------------------------------
191
+ //---------------------------------------------------------
@@ -34,7 +34,7 @@ function App() {
34
34
  try {
35
35
  const result = await aleoWorker.deployProgram(helloworld_program);
36
36
  console.log("Transaction:")
37
- console.log("https://explorer.hamp.app/transaction?id=" + result)
37
+ console.log("https://explorer.provable.com/transaction/" + result)
38
38
  alert("Transaction ID: " + result);
39
39
  } catch (e) {
40
40
  console.log(e)
@@ -34,7 +34,7 @@ function App() {
34
34
  try {
35
35
  const result = await aleoWorker.deployProgram(helloworld_program);
36
36
  console.log("Transaction:")
37
- console.log("https://explorer.hamp.app/transaction?id=" + result)
37
+ console.log("https://explorer.provable.com/transaction/" + result)
38
38
  alert("Transaction ID: " + result);
39
39
  } catch (e) {
40
40
  console.log(e)
@@ -0,0 +1,47 @@
1
+ import { Layout, Menu } from 'antd';
2
+ import { UserOutlined, CrownOutlined } from '@ant-design/icons';
3
+ import { Link, useLocation } from 'react-router-dom';
4
+
5
+ const { Sider } = Layout;
6
+
7
+ export const Sidebar = () => {
8
+ const location = useLocation();
9
+
10
+ const items = [
11
+ {
12
+ key: '/bidder',
13
+ icon: <UserOutlined />,
14
+ label: <Link to="/bidder">Bidder</Link>,
15
+ },
16
+ {
17
+ key: '/auctioneer',
18
+ icon: <CrownOutlined />,
19
+ label: <Link to="/auctioneer">Auctioneer</Link>,
20
+ }
21
+ ];
22
+
23
+ return (
24
+ <Sider
25
+ width={200}
26
+ theme="light"
27
+ style={{
28
+ position: 'fixed',
29
+ left: 0,
30
+ top: 0,
31
+ bottom: 0,
32
+ background: '#ffffff'
33
+ }}
34
+ >
35
+ <Menu
36
+ mode="inline"
37
+ selectedKeys={[location.pathname]}
38
+ style={{
39
+ height: '100%',
40
+ borderRight: '1px solid #f0f0f0',
41
+ background: '#ffffff'
42
+ }}
43
+ items={items}
44
+ />
45
+ </Sider>
46
+ );
47
+ };
@@ -0,0 +1,144 @@
1
+ import { Card, Form, Input, Button, List, Typography, message } from 'antd';
2
+ import { useState } from 'react';
3
+ import { AleoWorker } from "../workers/AleoWorker";
4
+
5
+ const aleoWorker = AleoWorker();
6
+
7
+ export const AuctioneerPage = () => {
8
+ const [receivedBids, setReceivedBids] = useState([]);
9
+ const [loading, setLoading] = useState(false);
10
+ const [resolveForm] = Form.useForm();
11
+ const [finishForm] = Form.useForm();
12
+
13
+ const layout = {
14
+ labelCol: { span: 6 },
15
+ wrapperCol: { span: 16 },
16
+ };
17
+
18
+ const handleResolveBids = async (values) => {
19
+ try {
20
+ setLoading(true);
21
+ const result = await aleoWorker.resolveBids(values.bid1, values.bid2);
22
+ message.success('Bids resolved successfully');
23
+ resolveForm.resetFields();
24
+ } catch (error) {
25
+ console.error('Error resolving bids:', error);
26
+ message.error('Failed to resolve bids');
27
+ } finally {
28
+ setLoading(false);
29
+ }
30
+ };
31
+
32
+ const handleFinishAuction = async (values) => {
33
+ try {
34
+ setLoading(true);
35
+ const result = await aleoWorker.finishAuction(values.winningBid);
36
+ message.success('Auction finished successfully');
37
+ finishForm.resetFields();
38
+ } catch (error) {
39
+ console.error('Error finishing auction:', error);
40
+ message.error('Failed to finish auction');
41
+ } finally {
42
+ setLoading(false);
43
+ }
44
+ };
45
+
46
+ return (
47
+ <div style={{ padding: '24px', maxWidth: '800px', margin: '0 auto' }}>
48
+ <Typography.Title level={2}>Auction Management</Typography.Title>
49
+
50
+ <Card
51
+ title={<Typography.Title level={4}>Current Auction Bids</Typography.Title>}
52
+ style={{ marginBottom: '24px' }}
53
+ >
54
+ <List
55
+ dataSource={receivedBids}
56
+ renderItem={(bid) => (
57
+ <List.Item>
58
+ <Typography.Text>
59
+ Bid ID: {bid.id} - Amount: {bid.amount}
60
+ </Typography.Text>
61
+ </List.Item>
62
+ )}
63
+ locale={{
64
+ emptyText: <Typography.Text type="secondary">No bids received yet</Typography.Text>
65
+ }}
66
+ />
67
+ </Card>
68
+
69
+ <Card
70
+ title={<Typography.Title level={4}>Compare and Resolve Bids</Typography.Title>}
71
+ style={{ marginBottom: '24px' }}
72
+ >
73
+ <Form
74
+ {...layout}
75
+ form={resolveForm}
76
+ onFinish={handleResolveBids}
77
+ >
78
+ <Form.Item
79
+ label="First Bid Record"
80
+ name="bid1"
81
+ tooltip="Enter the record of the first bid to compare"
82
+ rules={[{ required: true, message: 'Please enter the first bid record' }]}
83
+ >
84
+ <Input.TextArea
85
+ placeholder="Enter the complete bid record"
86
+ rows={3}
87
+ />
88
+ </Form.Item>
89
+ <Form.Item
90
+ label="Second Bid Record"
91
+ name="bid2"
92
+ tooltip="Enter the record of the second bid to compare"
93
+ rules={[{ required: true, message: 'Please enter the second bid record' }]}
94
+ >
95
+ <Input.TextArea
96
+ placeholder="Enter the complete bid record"
97
+ rows={3}
98
+ />
99
+ </Form.Item>
100
+ <Form.Item wrapperCol={{ offset: 6, span: 16 }}>
101
+ <Button
102
+ type="primary"
103
+ htmlType="submit"
104
+ loading={loading}
105
+ >
106
+ Compare and Resolve Bids
107
+ </Button>
108
+ </Form.Item>
109
+ </Form>
110
+ </Card>
111
+
112
+ <Card
113
+ title={<Typography.Title level={4}>Finalize Auction</Typography.Title>}
114
+ >
115
+ <Form
116
+ {...layout}
117
+ form={finishForm}
118
+ onFinish={handleFinishAuction}
119
+ >
120
+ <Form.Item
121
+ label="Winning Bid Record"
122
+ name="winningBid"
123
+ tooltip="Enter the record of the winning bid"
124
+ rules={[{ required: true, message: 'Please enter the winning bid record' }]}
125
+ >
126
+ <Input.TextArea
127
+ placeholder="Enter the complete winning bid record"
128
+ rows={3}
129
+ />
130
+ </Form.Item>
131
+ <Form.Item wrapperCol={{ offset: 6, span: 16 }}>
132
+ <Button
133
+ type="primary"
134
+ htmlType="submit"
135
+ loading={loading}
136
+ >
137
+ Finalize Auction with Winner
138
+ </Button>
139
+ </Form.Item>
140
+ </Form>
141
+ </Card>
142
+ </div>
143
+ );
144
+ };
@@ -0,0 +1,142 @@
1
+ import { Card, Form, Input, Button, List, Typography, message } from 'antd';
2
+ import { useState } from 'react';
3
+ import { AleoWorker } from "../workers/AleoWorker";
4
+
5
+ const aleoWorker = AleoWorker();
6
+
7
+ export const BidderPage = () => {
8
+ const [account, setAccount] = useState(null);
9
+ const [bids, setBids] = useState([]);
10
+ const [loading, setLoading] = useState(false);
11
+ const [bidForm] = Form.useForm();
12
+
13
+ const layout = {
14
+ labelCol: { span: 4 },
15
+ wrapperCol: { span: 20 },
16
+ };
17
+
18
+ const handleSetAccount = async (value) => {
19
+ try {
20
+ setLoading(true);
21
+ await aleoWorker.setAccount(value);
22
+ setAccount(value);
23
+ message.success('Account set successfully');
24
+ } catch (error) {
25
+ console.error('Error setting account:', error);
26
+ message.error('Failed to set account');
27
+ setAccount(null);
28
+ } finally {
29
+ setLoading(false);
30
+ }
31
+ };
32
+
33
+ const handlePlaceBid = async (values) => {
34
+ if (!account) {
35
+ message.error('Please set your account first');
36
+ return;
37
+ }
38
+
39
+ try {
40
+ setLoading(true);
41
+ const result = await aleoWorker.placeBid(values.amount, values.auctionId);
42
+ message.success('Bid placed successfully');
43
+ bidForm.resetFields();
44
+
45
+ // Add the new bid to the list
46
+ setBids(prevBids => [...prevBids, {
47
+ auctionId: values.auctionId,
48
+ amount: values.amount,
49
+ id: result.id // Assuming the worker returns a bid ID
50
+ }]);
51
+ } catch (error) {
52
+ console.error('Error placing bid:', error);
53
+ message.error('Failed to place bid');
54
+ } finally {
55
+ setLoading(false);
56
+ }
57
+ };
58
+
59
+ return (
60
+ <div style={{ padding: '24px' }}>
61
+ <Card
62
+ title="Aleo Account"
63
+ style={{ marginBottom: '24px' }}
64
+ >
65
+ <Form {...layout}>
66
+ <Form.Item
67
+ label="Private Key"
68
+ required
69
+ tooltip="Your Aleo private key is required to place bids"
70
+ >
71
+ <Input.Password
72
+ placeholder="Enter your Aleo private key"
73
+ onChange={(e) => handleSetAccount(e.target.value)}
74
+ value={account}
75
+ disabled={loading}
76
+ />
77
+ </Form.Item>
78
+ {account && (
79
+ <Form.Item wrapperCol={{ offset: 4 }}>
80
+ <Typography.Text type="success">
81
+ Account set ✓
82
+ </Typography.Text>
83
+ </Form.Item>
84
+ )}
85
+ </Form>
86
+ </Card>
87
+
88
+ <Card
89
+ title="Place Bid"
90
+ style={{ marginBottom: '24px' }}
91
+ >
92
+ <Form
93
+ {...layout}
94
+ form={bidForm}
95
+ onFinish={handlePlaceBid}
96
+ >
97
+ <Form.Item
98
+ label="Amount"
99
+ name="amount"
100
+ rules={[
101
+ { required: true, message: 'Please enter bid amount' },
102
+ { pattern: /^\d+$/, message: 'Please enter a valid number' }
103
+ ]}
104
+ >
105
+ <Input placeholder="Enter bid amount" disabled={!account || loading} />
106
+ </Form.Item>
107
+ <Form.Item
108
+ label="Auction ID"
109
+ name="auctionId"
110
+ rules={[{ required: true, message: 'Please enter auction ID' }]}
111
+ >
112
+ <Input placeholder="Enter auction ID" disabled={!account || loading} />
113
+ </Form.Item>
114
+ <Form.Item wrapperCol={{ offset: 4 }}>
115
+ <Button
116
+ type="primary"
117
+ htmlType="submit"
118
+ loading={loading}
119
+ disabled={!account}
120
+ >
121
+ Submit Bid
122
+ </Button>
123
+ </Form.Item>
124
+ </Form>
125
+ </Card>
126
+
127
+ <Card title="Open Bids">
128
+ <List
129
+ dataSource={bids}
130
+ renderItem={(bid) => (
131
+ <List.Item>
132
+ <Typography.Text>
133
+ Auction ID: {bid.auctionId} - Amount: {bid.amount}
134
+ </Typography.Text>
135
+ </List.Item>
136
+ )}
137
+ locale={{ emptyText: 'No bids placed yet' }}
138
+ />
139
+ </Card>
140
+ </div>
141
+ );
142
+ };
@@ -39,7 +39,7 @@ document.querySelector("#app").innerHTML = `
39
39
  <div class="card">
40
40
  <button onclick="window.execute()">Call Execute Function</button>
41
41
  <button onclick="window.key()">Get Private Key</button>
42
- <button onclick="window.deploy()">Deploy HelloWorld Program</button>
42
+ <button onclick="window.deploy()">Deploy Hello World Program</button>
43
43
  </div>
44
44
  <p class="read-the-docs">
45
45
  Click on the Aleo logo to learn more