From a8685d6f0e4bf43a80244145b9a08879612fabb9 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 5 Nov 2024 11:21:44 -0600 Subject: [PATCH 1/2] wallet1 --- .../harmonydb/sql/20241105-walletnames.sql | 5 + web/api/webrpc/wallet.go | 108 ++++++++++++++++++ web/static/actor-summary.mjs | 3 +- web/static/lib/cu-wallet.js | 63 ++++++++++ web/static/pages/wallet/index.html | 19 +++ web/static/pages/wallet/wallet.mjs | 81 +++++++++++++ 6 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 harmony/harmonydb/sql/20241105-walletnames.sql create mode 100644 web/api/webrpc/wallet.go create mode 100644 web/static/lib/cu-wallet.js create mode 100644 web/static/pages/wallet/index.html create mode 100644 web/static/pages/wallet/wallet.mjs diff --git a/harmony/harmonydb/sql/20241105-walletnames.sql b/harmony/harmonydb/sql/20241105-walletnames.sql new file mode 100644 index 000000000..d8e9d8cfd --- /dev/null +++ b/harmony/harmonydb/sql/20241105-walletnames.sql @@ -0,0 +1,5 @@ +CREATE TABLE wallet_names ( + id SERIAL PRIMARY KEY, + wallet_id VARCHAR NOT NULL, + name VARCHAR(60) NOT NULL +); diff --git a/web/api/webrpc/wallet.go b/web/api/webrpc/wallet.go new file mode 100644 index 000000000..5c4de7a9a --- /dev/null +++ b/web/api/webrpc/wallet.go @@ -0,0 +1,108 @@ +package webrpc + +import ( + "context" + "fmt" + "strings" + "sync" + + "github.com/filecoin-project/curio/deps/config" + "github.com/filecoin-project/curio/harmony/harmonydb" + "github.com/filecoin-project/go-address" + "golang.org/x/exp/maps" +) + +var walletOnce sync.Once + +func (a *WebRPC) WalletName(ctx context.Context, id string) (string, error) { + walletOnce.Do(func() { + populateWalletFriendlyNames(a.deps.Cfg.Addresses, a.deps.DB) + }) + walletFriendlyNamesLock.Lock() + defer walletFriendlyNamesLock.Unlock() + return walletFriendlyNames[id], nil +} + +func (a *WebRPC) WalletNameChange(ctx context.Context, id string, newName string) error { + _, err := a.deps.DB.Exec(ctx, `UDPATE wallet_names SET name = $1 WHERE id = $2`, newName, id) + if err != nil { + log.Errorf("failed to set wallet name for %s: %s", id, err) + return err + } + walletFriendlyNamesLock.Lock() + defer walletFriendlyNamesLock.Unlock() + walletFriendlyNames[id] = newName + return nil +} + +var walletFriendlyNames = map[string]string{} +var walletFriendlyNamesLock sync.Mutex + +func populateWalletFriendlyNames(addrGrps []config.CurioAddresses, db *harmonydb.DB) { + type nx struct { + purposes map[string]bool + miner map[string]bool + } + ex := map[string]*nx{} + all_purposes := []string{"PC_Ctrl", "Cmt_Ctrl", "Term_Ctrl"} + allMiners := map[string]bool{} + for _, addrList := range addrGrps { + n := map[string][]string{ + "PC_Ctrl": addrList.PreCommitControl, + "Cmt_Ctrl": addrList.CommitControl, + "Term_Ctrl": addrList.TerminateControl, + } + for name, addrs := range n { + for i, addr := range addrs { + a, err := address.NewFromString(addr) + if err != nil { + continue + } + allMiners[a.String()] = true + + if len(addrs) > 1 { + name = fmt.Sprintf("%s%d", name, i) + } + if res, ok := ex[a.String()]; ok { + res.purposes[name] = true + for _, miner := range addrList.MinerAddresses { + res.miner[miner] = true + } + } else { + var t = map[string]bool{} + for _, miner := range addrList.MinerAddresses { + t[miner] = true + } + ex[a.String()] = &nx{purposes: map[string]bool{name: true}, miner: t} + } + } + } + } + for addr, nx := range ex { + purpose := "" + miner := "" + if len(nx.purposes) != len(all_purposes) { // impossible to be 0 + purpose = strings.Join(maps.Keys(nx.purposes), ",") + } + if len(nx.miner) != len(allMiners) { // impoossible to be 0 + miner = "_" + strings.Join(maps.Keys(nx.miner), ",") + } + if purpose == "" && miner == "" { + purpose = "all" + } + walletFriendlyNames[addr] = purpose + miner + "Wallet" + } + + var idNames []struct { + ID string + Name string + } + err := db.Select(context.Background(), &idNames, `SELECT wallet_id as ID, name FROM wallet_names`) + if err != nil { + log.Errorf("failed to get wallet names: %s", err) + return + } + for _, idName := range idNames { + walletFriendlyNames[idName.ID] = idName.Name + } +} diff --git a/web/static/actor-summary.mjs b/web/static/actor-summary.mjs index 4643f05ba..d6f322553 100644 --- a/web/static/actor-summary.mjs +++ b/web/static/actor-summary.mjs @@ -1,5 +1,6 @@ import { LitElement, html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js'; import RPCCall from '/lib/jsonrpc.mjs'; +import '/lib/cu-wallet.mjs'; class Expirations extends LitElement { static properties = { @@ -249,7 +250,7 @@ class ActorSummary extends LitElement { ${this.data.map(entry => html` - ${entry.Address} + ${entry.CLayers.map(layer => html`${layer} `)} diff --git a/web/static/lib/cu-wallet.js b/web/static/lib/cu-wallet.js new file mode 100644 index 000000000..825d69867 --- /dev/null +++ b/web/static/lib/cu-wallet.js @@ -0,0 +1,63 @@ +import { LitElement, html } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js'; +import RPCCall from '/lib/jsonrpc.mjs'; + +class CuWallet extends LitElement { + static get properties() { + return { + wallet_id: { type: String } + }; + } + + constructor() { + super(); + this.wallet_id = ''; + } + + updated(changedProperties) { + if (changedProperties.has('wallet_id') && this.wallet_id) { + this.handleIdUpdate(); + } + } + + async handleIdUpdate() { + this.isProcessing = true; + try { + this.name = await RPCCall('WalletName', [this.wallet_id]); + } catch (error) { + console.error('Error during WalletName operation:', error); + } finally { + this.isProcessing = false; + } + this.requestUpdate(); + } + + nice_id() { + if (!this.wallet_id) return 'Not Set'; + if (this.name != '') return this.name; + return this.wallet_id.substring(0, 6) + '...' + this.wallet_id.substring(this.wallet_id.length - 6); + } + static styles = css` + @keyframes spinner { + to {transform: rotate(360deg);} + } + .spinner:before { + content: url('/favicon.svg'); + display: inline-block; + animation: spinner 1s linear infinite; + height: 12px; + } + `; + + render() { + return html` +
+ ${this.isProcessing ? html`` : ''} + 📛 + ${this.nice_id()} + navigator.clipboard.writeText(this.wallet_id)}>📋 +
+ `; + } +} + +customElements.define('cu-wallet', CuWallet); diff --git a/web/static/pages/wallet/index.html b/web/static/pages/wallet/index.html new file mode 100644 index 000000000..050cb600d --- /dev/null +++ b/web/static/pages/wallet/index.html @@ -0,0 +1,19 @@ + + + + + + Wallet + + + + + + + + + \ No newline at end of file diff --git a/web/static/pages/wallet/wallet.mjs b/web/static/pages/wallet/wallet.mjs new file mode 100644 index 000000000..4ebc85f62 --- /dev/null +++ b/web/static/pages/wallet/wallet.mjs @@ -0,0 +1,81 @@ +import { LitElement, html } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js'; +import RPCCall from '/lib/jsonrpc.mjs'; + +class CuWallet extends LitElement { + static get properties() { + return { + wallet_id: { type: String } + }; + } + + constructor() { + super(); + this.wallet_id = ''; + } + + updated(changedProperties) { + if (changedProperties.has('wallet_id') && this.wallet_id) { + this.handleIdUpdate(); + } + } + + async handleIdUpdate() { + this.isProcessing = true; + try { + let res = await RPCCall('WalletName', [this.wallet_id]); // TODO API call + this.name = res.name; + this.requestUpdate(); + } catch (error) { + console.error('Error during WalletName operation:', error); + } finally { + this.isProcessing = false; + } + } + + nice_id() { + if (!this.wallet_id) return 'Not Set'; + if (this.name != '') return this.name; + return this.wallet_id.substring(0, 6) + '...' + this.wallet_id.substring(this.wallet_id.length - 6); + } + async handleNameChange(new_nice_id) { + this.isProcessing = true; + this.name = new_nice_id; + this.requestUpdate(); + try { + await RPCCall('WalletNameChange', [this.wallet_id, new_nice_id]); // TODO API call + } catch (error) { + console.error('Error during WalletName operation:', error); + } finally { + this.isProcessing = false; + } + this.requestUpdate(); + } + static styles = css` + @keyframes spinner { + to {transform: rotate(360deg);} + } + .spinner:before { + content: url('/favicon.svg'); + display: inline-block; + animation: spinner 1s linear infinite; + height: 12px; + } + `; + + render() { + return html` +
+ ${this.isProcessing ? html`` : ''} + Full ID: ${this.wallet_id}
+
{ + e.preventDefault() + this.handleNameChange(e.target.walletName.value) + }}> + + +
+
`; + } +} + +customElements.define('wallet-component', CuWallet); From a97db933a2520ae0f4954011197e45c725daec2b Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Thu, 14 Nov 2024 09:15:30 -0600 Subject: [PATCH 2/2] wallet stuff --- web/api/webrpc/wallet.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/api/webrpc/wallet.go b/web/api/webrpc/wallet.go index 5c4de7a9a..6dbc85b2a 100644 --- a/web/api/webrpc/wallet.go +++ b/web/api/webrpc/wallet.go @@ -6,10 +6,12 @@ import ( "strings" "sync" + "golang.org/x/exp/maps" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/curio/deps/config" "github.com/filecoin-project/curio/harmony/harmonydb" - "github.com/filecoin-project/go-address" - "golang.org/x/exp/maps" ) var walletOnce sync.Once