mirror of
https://github.com/urbit/shrub.git
synced 2025-01-03 10:02:32 +03:00
btc: transaction history
This commit is contained in:
parent
fdfcf27ec4
commit
2158e9a4cd
@ -55,7 +55,7 @@
|
||||
^- (quip card _this)
|
||||
~& > '%btc-wallet initialized'
|
||||
=/ file
|
||||
[%file-server-action !>([%serve-dir /'~btc' /app/btc-wallet %.n %.n])]
|
||||
[%file-server-action !>([%serve-dir /'~btc' /app/btc-wallet %.n %.y])]
|
||||
=/ tile
|
||||
:- %launch-action
|
||||
!> :+ %add
|
||||
@ -165,25 +165,16 @@
|
||||
^- (quip card _this)
|
||||
?> (team:title our.bowl src.bowl)
|
||||
?> ?=([%all ~] path)
|
||||
=/ provider=json
|
||||
?~ prov ~
|
||||
[%s (scot %p host.u.prov)]
|
||||
=/ cb=(unit sats) current-balance:hc
|
||||
=/ wallet=json
|
||||
?~ walts ~
|
||||
%- pairs:enjs:format
|
||||
:~ balance+?~(cb ~ (numb:enjs:format u.cb))
|
||||
==
|
||||
=/ initial=json
|
||||
%+ frond:enjs:format
|
||||
%initial
|
||||
%- pairs:enjs:format
|
||||
:~ [%'provider' provider]
|
||||
[%'hasWallet' b+?=(^ walts)]
|
||||
[%wallet wallet]
|
||||
=/ initial=update
|
||||
:* %initial
|
||||
prov
|
||||
curr-xpub
|
||||
current-balance:hc
|
||||
current-history:hc
|
||||
btc-state
|
||||
==
|
||||
:_ this
|
||||
[%give %fact ~ %json !>(initial)]~
|
||||
[%give %fact ~ %btc-wallet-update !>(initial)]~
|
||||
::
|
||||
++ on-leave on-leave:def
|
||||
++ on-arvo on-arvo:def
|
||||
@ -380,9 +371,7 @@
|
||||
=+ fee=~(fee txb:bl u.poym)
|
||||
~& >> "{<vb>} vbytes, {<(div fee vb)>} sats/byte, {<fee>} sats fee"
|
||||
%- (slog [%leaf "PSBT: {<u.pb>}"]~)
|
||||
=/ psbt=json
|
||||
(frond:enjs:format %psbt [%s u.pb])
|
||||
[%give %fact ~[/all] %json !>(psbt)]~
|
||||
[(give-update [%psbt u.pb])]~
|
||||
:: update outgoing payment with a rawtx, if the txid is in poym's txis
|
||||
::
|
||||
++ update-poym-txis
|
||||
@ -408,8 +397,10 @@
|
||||
?: (poym-has-txid txid.ti.intr)
|
||||
(poym-to-history ti.intr)
|
||||
`state
|
||||
:- cards
|
||||
(handle-tx-info ti.intr)
|
||||
=^ cards2 state
|
||||
(handle-tx-info ti.intr)
|
||||
:_ state
|
||||
(weld cards cards2)
|
||||
::
|
||||
++ poym-has-txid
|
||||
|= txid=hexb
|
||||
@ -432,11 +423,11 @@
|
||||
`state
|
||||
=+ vout=(get-vout txos.u.poym)
|
||||
?~ vout ~|("poym-to-history: poym should always have an output" !!)
|
||||
:- ~
|
||||
=/ new-hest=hest (mk-hest ti xpub.u.poym our.bowl payee.u.poym u.vout)
|
||||
:- [(give-update %new-tx new-hest)]~
|
||||
%= state
|
||||
poym ~
|
||||
history
|
||||
(add-history-entry ti xpub.u.poym our.bowl payee.u.poym u.vout)
|
||||
poym ~
|
||||
history (~(put by history) txid.ti new-hest)
|
||||
==
|
||||
::
|
||||
++ get-vout
|
||||
@ -463,8 +454,12 @@
|
||||
=+ vout=(get-vout value.u.pay)
|
||||
?~ vout
|
||||
`(del-pend-piym txid.ti)
|
||||
=/ new-hest (mk-hest ti xpub.u.pay payer.u.pay `our.bowl u.vout)
|
||||
=. state (del-all-piym txid.ti payer.u.pay)
|
||||
`state(history (add-history-entry [ti xpub.u.pay payer.u.pay `our.bowl u.vout]))
|
||||
:- [(give-update %new-tx new-hest)]~
|
||||
%= state
|
||||
history (~(put by history) txid.ti new-hest)
|
||||
==
|
||||
::
|
||||
++ get-vout
|
||||
|= value=sats
|
||||
@ -476,7 +471,6 @@
|
||||
`idx
|
||||
$(os t.os, idx +(idx))
|
||||
::
|
||||
::
|
||||
++ del-pend-piym
|
||||
|= txid=hexb
|
||||
^- _state
|
||||
@ -493,22 +487,20 @@
|
||||
==
|
||||
--
|
||||
::
|
||||
++ add-history-entry
|
||||
++ mk-hest
|
||||
|= [ti=info:tx =xpub:bc payer=ship payee=(unit ship) vout=@ud]
|
||||
^- ^history
|
||||
=/ =hest
|
||||
:* xpub
|
||||
txid.ti
|
||||
confs.ti
|
||||
recvd.ti
|
||||
(turn inputs.ti |=(i=val:tx [i `payer]))
|
||||
%+ turn outputs.ti
|
||||
|= o=val:tx
|
||||
?: =(pos.o vout) :: check whether this is the output that went to payee
|
||||
[o payee]
|
||||
[o `payer]
|
||||
==
|
||||
(~(put by history) txid.hest hest)
|
||||
^- hest
|
||||
:* xpub
|
||||
txid.ti
|
||||
confs.ti
|
||||
recvd.ti
|
||||
(turn inputs.ti |=(i=val:tx [i `payer]))
|
||||
%+ turn outputs.ti
|
||||
|= o=val:tx
|
||||
?: =(pos.o vout) :: check whether this is the output that went to payee
|
||||
[o payee]
|
||||
[o `payer]
|
||||
==
|
||||
--
|
||||
::
|
||||
%fail-broadcast-tx
|
||||
@ -558,8 +550,10 @@
|
||||
`state(prov `u.prov(connected %.n))
|
||||
==
|
||||
:_ state
|
||||
:_ cards
|
||||
[%give %fact ~[/all] %btc-provider-status !>(s)]
|
||||
:* (give-update %btc-state btc-state)
|
||||
(give-update %change-provider prov)
|
||||
cards
|
||||
==
|
||||
::
|
||||
++ on-connected
|
||||
|= $: p=provider
|
||||
@ -668,8 +662,10 @@
|
||||
(handle-address-info address.p.upd utxos.p.upd used.p.upd)
|
||||
::
|
||||
%tx-info
|
||||
:- ~[(poke-internal [%close-pym info.p.upd])]
|
||||
(handle-tx-info info.p.upd)
|
||||
=/ [cards=(list card) sty=state-0]
|
||||
(handle-tx-info info.p.upd)
|
||||
:_ sty
|
||||
[(poke-internal [%close-pym info.p.upd]) cards]
|
||||
::
|
||||
%raw-tx
|
||||
:_ state
|
||||
@ -687,7 +683,7 @@
|
||||
::
|
||||
++ handle-tx-info
|
||||
|= ti=info:tx
|
||||
^- _state
|
||||
^- (quip card _state)
|
||||
|^
|
||||
=/ h (~(get by history) txid.ti)
|
||||
=. ahistorical-txs (~(del in ahistorical-txs) txid.ti)
|
||||
@ -697,21 +693,21 @@
|
||||
%+ turn (weld inputs.ti outputs.ti)
|
||||
|=(=val:tx address.val)
|
||||
is-our-address
|
||||
?: =(0 ~(wyt in our-addrs)) state
|
||||
?: =(0 ~(wyt in our-addrs)) `state
|
||||
=/ =xpub
|
||||
xpub.w:(need (address-coords:bl (snag 0 ~(tap in our-addrs)) ~(val by walts)))
|
||||
?~ h :: addresses in wallets, but tx not in history
|
||||
=. history
|
||||
%+ ~(put by history) txid.ti
|
||||
(mk-hest xpub our-addrs)
|
||||
state
|
||||
=/ new-hest=hest (mk-hest xpub our-addrs)
|
||||
=. history (~(put by history) txid.ti new-hest)
|
||||
:_ state
|
||||
[(give-update %new-tx new-hest)]~
|
||||
?. included.ti :: tx in history, but not in mempool/blocks
|
||||
state(history (~(del by history) txid.ti))
|
||||
%_ state
|
||||
history
|
||||
%+ ~(put by history) txid.ti
|
||||
u.h(confs confs.ti, recvd recvd.ti)
|
||||
==
|
||||
:_ state(history (~(del by history) txid.ti))
|
||||
[(give-update %cancel-tx txid.ti)]~
|
||||
=/ new-hest u.h(confs confs.ti, recvd recvd.ti)
|
||||
=. history (~(put by history) txid.ti new-hest)
|
||||
:_ state
|
||||
[(give-update %new-tx new-hest)]~
|
||||
::
|
||||
++ mk-hest
|
||||
:: has tx-info
|
||||
@ -904,6 +900,11 @@
|
||||
%btc-wallet-internal !>(intr)
|
||||
==
|
||||
::
|
||||
++ give-update
|
||||
|= upd=update
|
||||
^- card
|
||||
[%give %fact ~[/all] %btc-wallet-update !>(upd)]
|
||||
::
|
||||
++ is-broadcasting
|
||||
^- ?
|
||||
?~ poym %.n
|
||||
@ -938,4 +939,11 @@
|
||||
?~ curr-xpub ~
|
||||
(balance u.curr-xpub)
|
||||
::
|
||||
++ current-history
|
||||
^- ^history
|
||||
?~ curr-xpub ~
|
||||
%- ~(gas by *^history)
|
||||
%+ skim ~(tap by history)
|
||||
|= [txid =hest]
|
||||
=(u.curr-xpub xpub.hest)
|
||||
--
|
||||
|
@ -76,5 +76,116 @@
|
||||
:~ wid+(numb:enjs wid.h)
|
||||
dat+s+(scot %ux dat.h)
|
||||
==
|
||||
::
|
||||
++ update
|
||||
|= upd=update:btc-wallet
|
||||
^- json
|
||||
%+ frond -.upd
|
||||
?- -.upd
|
||||
%initial (initial upd)
|
||||
%change-provider (change-provider upd)
|
||||
%change-wallet (change-wallet upd)
|
||||
%psbt s+pb.upd
|
||||
%btc-state (btc-state btc-state.upd)
|
||||
%new-tx (hest hest.upd)
|
||||
%cancel-tx (hexb txid.upd)
|
||||
==
|
||||
::
|
||||
++ initial
|
||||
|= upd=update:btc-wallet
|
||||
?> ?=(%initial -.upd)
|
||||
^- json
|
||||
%- pairs
|
||||
:~ provider+(provider provider.upd)
|
||||
wallet+?~(wallet.upd ~ [%s u.wallet.upd])
|
||||
balance+?~(balance.upd ~ (numb u.balance.upd))
|
||||
history+(history history.upd)
|
||||
btc-state+(btc-state btc-state.upd)
|
||||
==
|
||||
::
|
||||
++ change-provider
|
||||
|= upd=update:btc-wallet
|
||||
?> ?=(%change-provider -.upd)
|
||||
^- json
|
||||
(provider provider.upd)
|
||||
::
|
||||
++ change-wallet
|
||||
|= upd=update:btc-wallet
|
||||
?> ?=(%change-wallet -.upd)
|
||||
^- json
|
||||
%- pairs
|
||||
:~ wallet+?~(wallet.upd ~ [%s u.wallet.upd])
|
||||
balance+?~(balance.upd ~ (numb u.balance.upd))
|
||||
history+(history history.upd)
|
||||
==
|
||||
::
|
||||
++ btc-state
|
||||
|= bs=btc-state:btc-wallet
|
||||
^- json
|
||||
%- pairs
|
||||
:~ block+(numb block.bs)
|
||||
fee+?~(fee.bs ~ (numb u.fee.bs))
|
||||
date+(sect t.bs)
|
||||
==
|
||||
::
|
||||
++ provider
|
||||
|= p=(unit provider:btc-wallet)
|
||||
^- json
|
||||
?~ p ~
|
||||
%- pairs
|
||||
:~ host+(ship host.u.p)
|
||||
connected+b+connected.u.p
|
||||
==
|
||||
::
|
||||
++ history
|
||||
|= hy=history:btc-wallet
|
||||
^- json
|
||||
:- %o
|
||||
^- (map @t json)
|
||||
%- ~(rep by hy)
|
||||
|= [[=txid:btc-wallet h=hest:btc-wallet] out=(map @t json)]
|
||||
^- (map @t json)
|
||||
(~(put by out) (scot %ux dat.txid) (hest h))
|
||||
::
|
||||
++ hest
|
||||
|= h=hest:btc-wallet
|
||||
^- json
|
||||
%- pairs
|
||||
:~ xpub+s+xpub.h
|
||||
txid+(hexb txid.h)
|
||||
confs+(numb confs.h)
|
||||
recvd+?~(recvd.h ~ (sect u.recvd.h))
|
||||
inputs+(vals inputs.h)
|
||||
outputs+(vals outputs.h)
|
||||
==
|
||||
::
|
||||
++ vals
|
||||
|= vl=(list [=val:tx:bitcoin s=(unit @p)])
|
||||
^- json
|
||||
:- %a
|
||||
%+ turn vl
|
||||
|= [v=val:tx:bitcoin s=(unit @p)]
|
||||
%- pairs
|
||||
:~ val+(val v)
|
||||
ship+?~(s ~ (ship u.s))
|
||||
==
|
||||
::
|
||||
++ val
|
||||
|= v=val:tx:bitcoin
|
||||
^- json
|
||||
%- pairs
|
||||
:~ txid+(hexb txid.v)
|
||||
pos+(numb pos.v)
|
||||
address+(address address.v)
|
||||
value+(numb value.v)
|
||||
==
|
||||
::
|
||||
++ address
|
||||
|= a=address:bitcoin
|
||||
^- json
|
||||
?- -.a
|
||||
%base58 [%s (rsh [3 2] (scot %uc +.a))]
|
||||
%bech32 [%s +.a]
|
||||
==
|
||||
--
|
||||
--
|
||||
|
14
pkg/arvo/mar/btc-wallet/update.hoon
Normal file
14
pkg/arvo/mar/btc-wallet/update.hoon
Normal file
@ -0,0 +1,14 @@
|
||||
/- *btc-wallet
|
||||
/+ bitcoin-json
|
||||
|_ upd=update
|
||||
++ grad %noun
|
||||
++ grow
|
||||
|%
|
||||
++ noun upd
|
||||
++ json (update:enjs:bitcoin-json upd)
|
||||
--
|
||||
++ grab
|
||||
|%
|
||||
++ noun update
|
||||
--
|
||||
--
|
@ -36,7 +36,6 @@
|
||||
[%succeed-broadcast-tx =txid]
|
||||
==
|
||||
::
|
||||
::
|
||||
:: Wallet Types
|
||||
::
|
||||
:: nixt: next indices to generate addresses from (non-change/change)
|
||||
@ -110,4 +109,21 @@
|
||||
outputs=(list [=val:tx s=(unit ship)])
|
||||
==
|
||||
+$ history (map txid hest)
|
||||
:: data to send to the frontend
|
||||
::
|
||||
+$ update
|
||||
$% $: %initial
|
||||
provider=(unit provider)
|
||||
wallet=(unit xpub)
|
||||
balance=(unit sats)
|
||||
=history
|
||||
=btc-state
|
||||
==
|
||||
[%change-provider provider=(unit provider)]
|
||||
[%change-wallet wallet=(unit xpub) balance=(unit sats) =history]
|
||||
[%psbt pb=@t]
|
||||
[%btc-state =btc-state]
|
||||
[%new-tx =hest]
|
||||
[%cancel-tx =txid]
|
||||
==
|
||||
--
|
||||
|
10
pkg/btc-wallet/package-lock.json
generated
10
pkg/btc-wallet/package-lock.json
generated
@ -1376,6 +1376,16 @@
|
||||
"tslib": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"@tlon/sigil-js": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@tlon/sigil-js/-/sigil-js-1.4.3.tgz",
|
||||
"integrity": "sha512-IaJUvAgXRmPFj5JA/MDfd+b+RFDhGdiMLfzJZKuFIQyl3Dl/3cC9HdDLCYSoK4GBTu3gZqoqi6wxZl5Xia/cSw==",
|
||||
"requires": {
|
||||
"invariant": "^2.2.4",
|
||||
"svgson": "^4.0.0",
|
||||
"transformation-matrix": "2.1.1"
|
||||
}
|
||||
},
|
||||
"@types/anymatch": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||
|
@ -40,6 +40,8 @@
|
||||
"@reach/tabs": "^0.10.5",
|
||||
"@tlon/indigo-light": "^1.0.5",
|
||||
"@tlon/indigo-react": "^1.2.8",
|
||||
"@tlon/sigil-js": "^1.4.3",
|
||||
"bip39": "^2.5.0",
|
||||
"bitcoinjs-lib": "^5.2.0",
|
||||
"bs58check": "^2.1.2",
|
||||
"buffer": "^6.0.3",
|
||||
@ -63,8 +65,7 @@
|
||||
"styled-system": "^5.1.5",
|
||||
"urbit-key-generation": "^0.18.0",
|
||||
"urbit-ob": "^5.0.0",
|
||||
"urbit-sigil-js": "^1.3.13",
|
||||
"bip39": "^2.5.0"
|
||||
"urbit-sigil-js": "^1.3.13"
|
||||
},
|
||||
"resolutions": {
|
||||
"natives": "1.1.3"
|
||||
|
@ -54,9 +54,9 @@ export default class Balance extends Component {
|
||||
|
||||
|
||||
render() {
|
||||
const sats = (this.props.state.wallet) ?
|
||||
(this.props.state.wallet.balance || 0) : 0;
|
||||
const sats = (this.props.state.balance || 0);
|
||||
const value = currencyFormat(sats, this.state.conversion, this.state.denomination);
|
||||
const sendDisabled = (sats === 0);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -74,6 +74,7 @@ export default class Balance extends Component {
|
||||
width='100%'
|
||||
backgroundColor="white"
|
||||
borderRadius="32px"
|
||||
justifyContent="space-between"
|
||||
mb={5}
|
||||
p={5}
|
||||
>
|
||||
@ -91,10 +92,12 @@ export default class Balance extends Component {
|
||||
</Col>
|
||||
<Row flexDirection="row-reverse">
|
||||
<Button children="Send"
|
||||
disabled={sendDisabled}
|
||||
fontSize={1}
|
||||
fontWeight="bold"
|
||||
color="lighterGray"
|
||||
backgroundColor="veryLightGray"
|
||||
color={sendDisabled ? "lighterGray" : "white"}
|
||||
backgroundColor={sendDisabled ? "veryLightGray" : "orange"}
|
||||
style={{cursor: sendDisabled ? "default" : "pointer" }}
|
||||
borderColor="none"
|
||||
borderRadius="24px"
|
||||
py="24px"
|
||||
@ -106,6 +109,7 @@ export default class Balance extends Component {
|
||||
fontWeight="bold"
|
||||
color="orange"
|
||||
backgroundColor="midOrange"
|
||||
style={{cursor:"pointer"}}
|
||||
borderColor="none"
|
||||
borderRadius="24px"
|
||||
py="24px"
|
||||
|
67
pkg/btc-wallet/src/js/components/lib/sigil.js
Normal file
67
pkg/btc-wallet/src/js/components/lib/sigil.js
Normal file
@ -0,0 +1,67 @@
|
||||
import React, { memo } from 'react';
|
||||
import { sigil, reactRenderer } from '@tlon/sigil-js';
|
||||
import { Box } from '@tlon/indigo-react';
|
||||
|
||||
export const foregroundFromBackground = (background) => {
|
||||
const rgb = {
|
||||
r: parseInt(background.slice(1, 3), 16),
|
||||
g: parseInt(background.slice(3, 5), 16),
|
||||
b: parseInt(background.slice(5, 7), 16)
|
||||
};
|
||||
const brightness = (299 * rgb.r + 587 * rgb.g + 114 * rgb.b) / 1000;
|
||||
const whiteBrightness = 255;
|
||||
|
||||
return whiteBrightness - brightness < 50 ? 'black' : 'white';
|
||||
};
|
||||
|
||||
export const Sigil = memo(
|
||||
({
|
||||
classes = '',
|
||||
color,
|
||||
foreground = '',
|
||||
ship,
|
||||
size,
|
||||
svgClass = '',
|
||||
icon = false,
|
||||
padding = 0,
|
||||
display = 'inline-block'
|
||||
}) => {
|
||||
const innerSize = Number(size) - 2 * padding;
|
||||
const paddingPx = `${padding}px`;
|
||||
const foregroundColor = foreground
|
||||
? foreground
|
||||
: foregroundFromBackground(color);
|
||||
return ship.length > 14 ? (
|
||||
<Box
|
||||
backgroundColor={color}
|
||||
borderRadius={icon ? '1' : '0'}
|
||||
display={display}
|
||||
height={size}
|
||||
width={size}
|
||||
className={classes}
|
||||
/>
|
||||
) : (
|
||||
<Box
|
||||
display={display}
|
||||
borderRadius={icon ? '1' : '0'}
|
||||
flexBasis={size}
|
||||
backgroundColor={color}
|
||||
padding={paddingPx}
|
||||
className={classes}
|
||||
>
|
||||
{sigil({
|
||||
patp: ship,
|
||||
renderer: reactRenderer,
|
||||
size: innerSize,
|
||||
icon,
|
||||
colors: [color, foregroundColor],
|
||||
class: svgClass
|
||||
})}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Sigil.displayName = 'Sigil';
|
||||
|
||||
export default Sigil;
|
@ -14,7 +14,7 @@ export default class StartupModal extends Component {
|
||||
render() {
|
||||
let modal = null;
|
||||
|
||||
if (this.props.state.hasWallet && this.props.state.provider) {
|
||||
if (this.props.state.wallet && this.props.state.provider) {
|
||||
return null;
|
||||
} else if (!this.props.state.provider){
|
||||
modal =
|
||||
@ -22,7 +22,7 @@ export default class StartupModal extends Component {
|
||||
api={this.props.api}
|
||||
providerPerms={this.props.state.providerPerms}
|
||||
/>
|
||||
} else if (!this.props.state.hasWallet){
|
||||
} else if (!this.props.state.wallet){
|
||||
modal = <WalletModal api={this.props.api}/>
|
||||
}
|
||||
return (
|
||||
|
87
pkg/btc-wallet/src/js/components/lib/transaction.js
Normal file
87
pkg/btc-wallet/src/js/components/lib/transaction.js
Normal file
@ -0,0 +1,87 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Icon,
|
||||
Row,
|
||||
Text,
|
||||
Button,
|
||||
Col,
|
||||
LoadingSpinner,
|
||||
} from '@tlon/indigo-react';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { Sigil } from './sigil.js'
|
||||
import TxAction from './tx-action.js'
|
||||
import TxCounterparty from './tx-counterparty.js'
|
||||
|
||||
export default class Transaction extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const pending = (!this.props.tx.recvd);
|
||||
console.log("transaction", this.props.tx.recvd);
|
||||
|
||||
const weSent = _.find(this.props.tx.inputs, (input) => {
|
||||
return (input.ship === window.ship);
|
||||
});
|
||||
|
||||
let action = (weSent) ? "sent" : "recv";
|
||||
|
||||
let counterShip;
|
||||
let counterAddress;
|
||||
let value;
|
||||
let sign;
|
||||
|
||||
if (action === "sent") {
|
||||
let counter = _.find(this.props.tx.outputs, (output) => {
|
||||
return (output.ship !== window.ship);
|
||||
});
|
||||
counterShip = counter.ship;
|
||||
counterAddress = counter.val.address;
|
||||
value = counter.val.value;
|
||||
sign = '-'
|
||||
}
|
||||
else if (action === "recv") {
|
||||
let incoming = _.find(this.props.tx.outputs, (output) => {
|
||||
return (output.ship === window.ship);
|
||||
});
|
||||
value = incoming.val.value;
|
||||
|
||||
let counter = _.find(this.props.tx.inputs, (input) => {
|
||||
return (input.ship !== window.ship);
|
||||
});
|
||||
counterShip = counter.ship;
|
||||
counterAddress = counter.val.address;
|
||||
sign = '';
|
||||
}
|
||||
|
||||
const failure = Boolean(this.props.tx.failure);
|
||||
if (failure) action = "fail";
|
||||
|
||||
|
||||
return (
|
||||
<Col
|
||||
width='100%'
|
||||
backgroundColor="white"
|
||||
justifyContent="space-between"
|
||||
mb="16px"
|
||||
>
|
||||
<Row justifyContent="space-between" alignItems="center">
|
||||
<TxAction action={action} pending={pending}/>
|
||||
<Text fontSize="14px" alignItems="center" color="gray">
|
||||
{sign}{value} sats
|
||||
</Text>
|
||||
</Row>
|
||||
<Box ml="11px" borderLeft="2px solid black" height="4px">
|
||||
</Box>
|
||||
<Row justifyContent="space-between" alignItems="center">
|
||||
<TxCounterparty address={counterAddress} ship={counterShip}/>
|
||||
<Text fontSize="14px">{sign}$5</Text>
|
||||
</Row>
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
}
|
@ -8,6 +8,8 @@ import {
|
||||
Col,
|
||||
} from '@tlon/indigo-react';
|
||||
|
||||
import Transaction from './transaction.js';
|
||||
|
||||
|
||||
export default class Transactions extends Component {
|
||||
constructor(props) {
|
||||
@ -16,19 +18,21 @@ export default class Transactions extends Component {
|
||||
|
||||
|
||||
render() {
|
||||
const body = (this.props.state.history.length <= 0)
|
||||
? <Text color="gray" fontSize={2} fontWeight="bold">No Transactions Yet</Text>
|
||||
: this.props.state.history.map((tx, i) => {
|
||||
return(<Transaction tx={tx} key={i}/>)
|
||||
});
|
||||
|
||||
return (
|
||||
<Col
|
||||
height="100px"
|
||||
width='100%'
|
||||
backgroundColor="white"
|
||||
borderRadius="32px"
|
||||
flexGrow="1"
|
||||
mb={5}
|
||||
p={5}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Text color="gray" fontSize={2} fontWeight="bold">No Transactions Yet</Text>
|
||||
{body}
|
||||
</Col>
|
||||
);
|
||||
}
|
||||
|
65
pkg/btc-wallet/src/js/components/lib/tx-action.js
Normal file
65
pkg/btc-wallet/src/js/components/lib/tx-action.js
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Icon,
|
||||
Row,
|
||||
Text,
|
||||
Button,
|
||||
Col,
|
||||
LoadingSpinner,
|
||||
} from '@tlon/indigo-react';
|
||||
|
||||
import { Sigil } from './sigil.js'
|
||||
|
||||
|
||||
export default class TxAction extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const leftIcon =
|
||||
(this.props.action === "sent") ? "ArrowSouth" :
|
||||
(this.props.action === "recv") ? "ArrowNorth" :
|
||||
(this.props.action === "fail") ? "X" :
|
||||
"NullIcon";
|
||||
|
||||
const actionColor =
|
||||
(this.props.action === "sent") ? "sentBlue" :
|
||||
(this.props.action === "recv") ? "recvGreen" :
|
||||
(this.props.action === "fail") ? "gray" :
|
||||
"red";
|
||||
|
||||
const actionText =
|
||||
(this.props.action === "sent") ? "Sent BTC" :
|
||||
(this.props.action === "recv") ? "Received BTC" :
|
||||
(this.props.action === "fail") ? "Failed" :
|
||||
"error";
|
||||
|
||||
const pending = (!this.props.pending) ? null :
|
||||
<LoadingSpinner
|
||||
background="midOrange"
|
||||
foreground="orange"
|
||||
/>
|
||||
|
||||
return (
|
||||
<Row alignItems="center">
|
||||
<Box backgroundColor={actionColor}
|
||||
width="24px"
|
||||
height="24px"
|
||||
textAlign="center"
|
||||
alignItems="center"
|
||||
borderRadius="2px"
|
||||
mr={2}
|
||||
p={1}
|
||||
>
|
||||
<Icon icon={leftIcon} color="white"/>
|
||||
</Box>
|
||||
<Text color={actionColor} fontSize="14px">{actionText}</Text>
|
||||
<Icon color={actionColor} icon="ArrowNorthEast" ml={1} mr={2}/>
|
||||
{pending}
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
51
pkg/btc-wallet/src/js/components/lib/tx-counterparty.js
Normal file
51
pkg/btc-wallet/src/js/components/lib/tx-counterparty.js
Normal file
@ -0,0 +1,51 @@
|
||||
import React, { Component } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Icon,
|
||||
Row,
|
||||
Text,
|
||||
Button,
|
||||
Col,
|
||||
} from '@tlon/indigo-react';
|
||||
|
||||
import { Sigil } from './sigil.js'
|
||||
import TxAction from './tx-action.js'
|
||||
|
||||
export default class TxCounterparty extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const icon = (this.props.ship)
|
||||
? <Sigil
|
||||
ship={this.props.ship}
|
||||
size={24}
|
||||
color="black"
|
||||
classes={''}
|
||||
icon
|
||||
padding={5}
|
||||
/>
|
||||
: <Box backgroundColor="lighterGray"
|
||||
width="24px"
|
||||
height="24px"
|
||||
textAlign="center"
|
||||
alignItems="center"
|
||||
borderRadius="2px"
|
||||
p={1}
|
||||
>
|
||||
<Icon icon="NullIcon" color="black"/>
|
||||
</Box>
|
||||
const addressText = this.props.address.slice(0, 6) + '...' +
|
||||
this.props.address.slice(-6);
|
||||
const text = (this.props.ship || addressText);
|
||||
|
||||
return (
|
||||
<Row alignItems="center">
|
||||
{icon}
|
||||
<Text ml={2} mono fontSize="14px" color="gray">{text}</Text>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
@ -37,7 +37,6 @@ export class Root extends Component {
|
||||
position='absolute'
|
||||
alignItems='center'
|
||||
backgroundColor='lightOrange'
|
||||
height='100%'
|
||||
width='100%'
|
||||
px={[0,4]}
|
||||
pb={[0,4]}
|
||||
|
@ -109,6 +109,9 @@ const theme = {
|
||||
orange: "rgba(255, 153, 0, 1)",
|
||||
midOrange: "rgba(255, 153, 0, 0.2)",
|
||||
lightOrange: "rgba(255, 153, 0, 0.08)",
|
||||
|
||||
sentBlue: "rgba(33,157,255,1)",
|
||||
recvGreen: "rgba(0,159,101,1)",
|
||||
},
|
||||
fonts: {
|
||||
sans: `"Inter", "Inter UI", -apple-system, BlinkMacSystemFont, 'San Francisco', 'Helvetica Neue', Arial, sans-serif`,
|
||||
|
@ -2,13 +2,22 @@ import _ from 'lodash';
|
||||
|
||||
export class InitialReducer {
|
||||
reduce(json, state) {
|
||||
console.log('json', json);
|
||||
let data = _.get(json, 'initial', false);
|
||||
console.log('data', data);
|
||||
if (data) {
|
||||
console.log('InitialReducer', data);
|
||||
state.provider = data.provider;
|
||||
state.hasWallet = data.hasWallet;
|
||||
state.wallet = data.wallet;
|
||||
state.balance = data.balance;
|
||||
state.btcState = data['btc-state'];
|
||||
state.history = this.reduceHistory(data.history);
|
||||
}
|
||||
}
|
||||
|
||||
reduceHistory(history) {
|
||||
return Object.values(history).sort((hest1, hest2) => {
|
||||
if (hest1.recvd === null) return -1;
|
||||
if (hest2.recvd === null) return +1;
|
||||
return (hest2.recvd - hest1.recvd)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -7,23 +7,71 @@ export class UpdateReducer {
|
||||
if (json.providerStatus) {
|
||||
this.reduceProviderStatus(json.providerStatus, state);
|
||||
}
|
||||
if (json.connected) {
|
||||
this.reduceConnected(json.connected, state);
|
||||
if (json["change-provider"]) {
|
||||
this.reduceChangeProvider(json["change-provider"], state);
|
||||
}
|
||||
if (json["change-wallet"]) {
|
||||
this.changeWallet(json["change-wallet"], state);
|
||||
}
|
||||
if (json.psbt) {
|
||||
this.reducePsbt(json.psbt, state);
|
||||
}
|
||||
if (json["btc-state"]) {
|
||||
this.reduceBtcState(json["btc-state"], state);
|
||||
}
|
||||
if (json["new-tx"]) {
|
||||
this.reduceNewTx(json["new-tx"], state);
|
||||
}
|
||||
if (json["cancel-tx"]) {
|
||||
this.reduceCancelTx(json["cancel-tx"], state);
|
||||
}
|
||||
}
|
||||
|
||||
reduceProviderStatus(json, state) {
|
||||
state.providerPerms[json.provider] = json.permitted;
|
||||
}
|
||||
|
||||
reduceConnected(json, state) {
|
||||
state.provider = true;
|
||||
reduceChangeProvider(json, state) {
|
||||
state.provider = json;
|
||||
}
|
||||
|
||||
reduceChangeWallet(json, state) {
|
||||
state.wallet = json;
|
||||
}
|
||||
|
||||
reducePsbt(json, state) {
|
||||
state.psbt = json;
|
||||
}
|
||||
|
||||
reduceBtcState(json, state) {
|
||||
state.btcState = json;
|
||||
}
|
||||
|
||||
reduceNewTx(json, state) {
|
||||
console.log("new-tx.....", json);
|
||||
let old = _.findIndex(state.history, (h) => {
|
||||
return ( h.txid.dat === json.txid.dat &&
|
||||
h.txid.wid === json.txid.wid );
|
||||
});
|
||||
if (old !== -1) {
|
||||
delete state.history[old];
|
||||
}
|
||||
if (json.recvd === null) {
|
||||
state.history.unshift(json);
|
||||
}
|
||||
// we expect history to have null recvd values first, and the rest in
|
||||
// descending order
|
||||
let insertionIndex = _.findIndex(state.history, (h) => {
|
||||
console.log("h", h);
|
||||
return ((h.recvd < json.recvd) && (h.recvd !== null));
|
||||
});
|
||||
state.history.splice(insertionIndex, 0, json);
|
||||
}
|
||||
|
||||
reduceCancelTx(json, state) {
|
||||
let entryIndex = _.findIndex(state.history, (h) => {
|
||||
return ((json.wid === h.txid.wid) && (json.dat === h.txid.dat));
|
||||
});
|
||||
state.history[entryIndex].failure = true;
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,11 @@ class Store {
|
||||
constructor() {
|
||||
this.state = {
|
||||
providerPerms: {},
|
||||
provider: true,
|
||||
hasWallet: true,
|
||||
wallet: {},
|
||||
provider: null,
|
||||
wallet: null,
|
||||
balance: null,
|
||||
btcState: null,
|
||||
history: [],
|
||||
psbt: '',
|
||||
};
|
||||
|
||||
@ -22,8 +24,6 @@ class Store {
|
||||
|
||||
handleEvent(data) {
|
||||
let json = data.data;
|
||||
|
||||
console.log(json);
|
||||
this.initialReducer.reduce(json, this.state);
|
||||
this.updateReducer.reduce(json, this.state);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user