Skip to content
Projects
Groups
Snippets
Help
Sign in / Register
Toggle navigation
Minds Frontend
Project overview
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
404
Merge Requests
57
CI / CD
Security & Compliance
Packages
Wiki
Snippets
Members
Collapse sidebar
Close sidebar
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Minds
Minds Frontend
Commits
c45fd44f
Commit
c45fd44f
authored
27 minutes ago
by
Olivia Madrid
Browse files
Options
Download
(feat): wallet balance tokens and service updates
parent
d005f0d4
tokens-balance-2282
1 merge request
!680
WIP: token balance component
Pipeline
#101091169
running with stages
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
320 additions
and
137 deletions
+320
-137
src/app/common/components/shadowbox-header-tabs/shadowbox-header-tabs.component.html
View file @
c45fd44f
...
...
@@ -15,6 +15,15 @@
*ngIf=
"tab.value || tab.value === 0"
[ngSwitch]=
"tab?.unit"
>
<ng-template
ngSwitchCase=
"tokens"
>
{{ tab.value | token: 18 | number: '1.0-3' }}
</ng-template>
<ng-template
ngSwitchCase=
"eth"
>
{{ tab.value | token: 18 | number: '1.0-3' }}
</ng-template>
<ng-template
ngSwitchCase=
"btc"
>
{{ tab.value | token: 18 | number: '1.0-3' }}
</ng-template>
<ng-template
ngSwitchCase=
"number"
>
{{ tab.value | number }}
</ng-template>
...
...
This diff is collapsed.
src/app/modules/wallet/v2/balance-tokens/balance-tokens.component.html
View file @
c45fd44f
...
...
@@ -5,20 +5,16 @@
<div
class=
"m-walletBalance--tokens__balanceTitle"
>
Token Balance
</div>
<div
class=
"m-walletBalance--tokens__balanceValWrapper"
>
<span
class=
"m-walletBalance--tokens__balanceVal--int"
>
{{
to
talBalance.int
to
kenBalance.int | number
}}
</span
>
.
<span
class=
"m-walletBalance--tokens__balanceVal--frac"
>
{{
totalBalance.frac
}}
</span>
><span
class=
"m-walletBalance--tokens__balanceVal--frac"
*ngIf=
"tokenBalance.frac"
>
.{{ tokenBalance.frac | token: 15 | number: '3.0-0' }}
</span
>
</div>
</div>
<a
class=
"m-walletBalance--tokens__buyButtonWrapper"
routerLink=
"/tokens"
><m-shadowboxSubmitButton
[disabled]=
"!session.getLoggedInUser().rewards"
>
Buy tokens
</m-shadowboxSubmitButton
></a
>
<ng-container
*ngTemplateOutlet=
"buyTokens"
></ng-container>
</div>
<div
class=
"m-walletBalance--tokens__equationSymbol"
>
=
</div>
<div
class=
"m-walletBalance--tokens__balanceWrapper--subtotal"
>
...
...
@@ -29,12 +25,12 @@
</div>
<div
class=
"m-walletBalance--tokens__balanceValWrapper"
>
<span
class=
"m-walletBalance--tokens__balanceVal--int"
>
{{
offchainBalance.int |
token: 18 | number: '1.0-0'
offchainBalance.int |
number
}}
</span
><span
class=
"m-walletBalance--tokens__balanceVal--frac"
*ngIf=
"offchainBalance.frac"
>
.{{ offchainBalance.frac }}
</span
>
.{{ offchainBalance.frac
| token: 15 | number: '3.0-0'
}}
</span
>
tokens
</div>
...
...
@@ -43,20 +39,17 @@
<div
class=
"m-walletBalance--tokens__balanceWrapper--subtotal"
>
<div
class=
"m-walletBalance--tokens__balanceTitle"
>
On-Chain
<m-tooltip
icon=
"help"
>
A
short description of On-chain
</m-tooltip
>
A
"short description of On-chain" lol
</m-tooltip
>
</div>
<div
class=
"m-walletBalance--tokens__balanceValWrapper"
>
<span
class=
"m-walletBalance--tokens__balanceVal--int"
>
{{
onchainBalance.int |
token: 18 | number: '1.0-0'
onchainBalance.int |
number
}}
</span
><span
class=
"m-walletBalance--tokens__balanceVal--frac"
*ngIf=
"onchainBalance.frac"
>
.{{
(onchainBalance.total - onchainBalance.total.toFixed(0)) * 1000
| number: '1.0-0'
}}
</span
>
.{{ onchainBalance.frac | token: 15 | number: '3.0-0' }}
</span
>
tokens
</div>
...
...
@@ -69,11 +62,19 @@
<div
class=
"m-walletBalance--tokens__payout"
>
Daily estimated payout
<span>
{{ estimatedTokenPayout | token: 18 | number: '1.0-3' }}
</span>
tokens. Next payout in
<span>
{{ nextPayout | timediff: true }}
</span>
(Daily
at 2:00am UTC)
tokens. Next payout in
<span>
{{ nextPayout | timediff }}
</span>
(Daily
at 2:00am UTC)
</div>
</ng-container>
<ng-template
#buyTokens
>
<a
class=
"m-walletBalance--tokens__buyButtonWrapper"
routerLink=
"/tokens"
><m-shadowboxSubmitButton
[disabled]=
"!session.getLoggedInUser().rewards"
>
Buy tokens
</m-shadowboxSubmitButton
></a
>
</ng-template>
<ng-template
#loading
>
<h2>
...
</h2>
</ng-template>
This diff is collapsed.
src/app/modules/wallet/v2/balance-tokens/balance-tokens.component.scss
View file @
c45fd44f
...
...
@@ -49,6 +49,9 @@ m-walletBalance--tokens {
}
.m-walletBalance--tokens__balanceWrapper--subtotal
{
.m-walletBalance--tokens__balanceTitle
{
min-width
:
78px
;
}
.m-walletBalance--tokens__balanceValWrapper
{
font-size
:
13px
;
line-height
:
18px
;
...
...
@@ -102,7 +105,6 @@ m-walletBalance--tokens {
margin-top
:
10px
;
}
// TODO make equationLeft flex-direction:column at a certain width
@media
screen
and
(
max-width
:
800px
)
{
.m-walletBalance--tokens__equationLeft
{
flex-direction
:
column
;
...
...
This diff is collapsed.
src/app/modules/wallet/v2/balance-tokens/balance-tokens.component.ts
View file @
c45fd44f
...
...
@@ -4,9 +4,12 @@ import {
OnDestroy
,
ChangeDetectionStrategy
,
ChangeDetectorRef
,
Input
,
}
from
'
@angular/core
'
;
import
{
Client
}
from
'
../../../../services/api/client
'
;
import
{
Session
}
from
'
../../../../services/session
'
;
import
{
WalletDashboardService
}
from
'
./../dashboard.service
'
;
import
*
as
BN
from
'
bn.js
'
;
@
Component
({
selector
:
'
m-walletBalance--tokens
'
,
...
...
@@ -14,91 +17,71 @@ import { Session } from '../../../../services/session';
changeDetection
:
ChangeDetectionStrategy
.
OnPush
,
})
export
class
WalletBalanceTokensV2Component
implements
OnInit
,
OnDestroy
{
@
Input
()
wallet
;
constructor
(
protected
client
:
Client
,
protected
cd
:
ChangeDetectorRef
,
protected
session
:
Session
protected
session
:
Session
,
protected
walletService
:
WalletDashboardService
)
{}
tokenBalance
;
offchainBalance
;
onchainBalance
;
inProgress
=
true
;
protected
updateTimer$
;
nextPayout
;
estimatedTokenPayout
;
totalBalance
=
{
total
:
123.345777892347923487
,
int
:
123
,
frac
:
345
,
};
offchainBalance
=
{
total
:
1.34
,
int
:
1
,
frac
:
34
,
};
onchainBalance
=
{
total
:
122
,
int
:
122
,
frac
:
0
,
};
ngOnInit
()
{
this
.
loadBalances
();
this
.
loadPayout
();
this
.
tokenBalance
=
this
.
formatBalance
(
this
.
wallet
.
tokens
.
balance
);
this
.
offchainBalance
=
this
.
formatBalance
(
this
.
wallet
.
offchain
.
balance
);
this
.
onchainBalance
=
this
.
formatBalance
(
this
.
wallet
.
onchain
.
balance
);
const
payouts
:
any
=
this
.
walletService
.
getTokenPayoutOverview
();
console
.
log
(
'
888
'
,
payouts
);
this
.
nextPayout
=
payouts
.
nextPayout
;
this
.
estimatedTokenPayout
=
payouts
.
currentReward
;
this
.
inProgress
=
false
;
this
.
updateTimer$
=
setInterval
(
this
.
updateNextPayout
.
bind
(
this
),
1000
);
this
.
detectChanges
();
}
ngOnDestroy
()
{
clearInterval
(
this
.
updateTimer$
);
}
async
loadBalances
()
{
try
{
const
result
:
any
=
await
this
.
client
.
get
(
`api/v2/blockchain/contributions/overview`
);
// this.totalBalance = result. ;
updateNextPayout
()
{
if
(
this
.
nextPayout
)
{
this
.
nextPayout
--
;
this
.
detectChanges
();
}
catch
(
e
)
{
console
.
error
(
e
);
}
}
async
loadPayout
()
{
try
{
const
result
:
any
=
await
this
.
client
.
get
(
`api/v2/blockchain/contributions/overview`
);
this
.
nextPayout
=
result
.
nextPayout
;
this
.
estimatedTokenPayout
=
result
.
currentReward
;
formatBalance
(
balance
)
{
const
formattedBalance
=
{
total
:
balance
,
int
:
0
,
frac
:
null
,
};
if
(
balance
<=
0
)
{
return
formattedBalance
;
}
this
.
detectChanges
();
}
catch
(
e
)
{
console
.
error
(
e
);
if
(
balance
.
length
>
18
)
{
formattedBalance
.
int
=
balance
.
slice
(
0
,
-
18
);
}
}
const
decimals
=
balance
.
slice
(
-
18
);
updateNextPayout
()
{
if
(
this
.
nextPayout
)
{
this
.
nextPayout
--
;
this
.
detectChanges
();
console
.
log
(
'
888iszero?
'
,
!
new
BN
(
decimals
).
isZero
());
if
(
!
new
BN
(
decimals
).
isZero
()
||
decimals
.
slice
(
0
,
3
)
!==
'
000
'
)
{
formattedBalance
.
frac
=
decimals
;
}
console
.
log
(
'
888
'
,
formattedBalance
);
return
formattedBalance
;
}
detectChanges
()
{
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
}
//get total balance () {
// return total: #, int: #, dec: #
// }
//get offchain balance
// get onchain balance
// process all 3 balances
// option a: ~~total will truncate??
// option b: var num = (15.46974).toFixed(2) // returns str
}
This diff is collapsed.
src/app/modules/wallet/v2/chart/chart.component.ts
View file @
c45fd44f
...
...
@@ -42,7 +42,7 @@ export class WalletChartComponent implements OnInit {
ngOnInit
()
{
this
.
activeTimespan
=
this
.
timespans
[
0
];
this
.
data
[
'
visualisation
'
]
=
this
.
walletService
.
getTokenChart
Data
(
this
.
data
[
'
visualisation
'
]
=
this
.
walletService
.
getTokenChart
(
this
.
activeTimespan
);
}
...
...
@@ -51,6 +51,6 @@ export class WalletChartComponent implements OnInit {
this
.
activeTimespan
=
this
.
timespans
.
find
(
ts
=>
ts
.
id
===
$event
.
timespanId
);
this
.
data
=
this
.
walletService
.
getTokenChart
Data
(
this
.
activeTimespan
);
this
.
data
=
this
.
walletService
.
getTokenChart
(
this
.
activeTimespan
);
}
}
This diff is collapsed.
src/app/modules/wallet/v2/dashboard.component.html
View file @
c45fd44f
...
...
@@ -20,6 +20,7 @@
<div
class=
"m-shadowboxLayout__body"
>
<m-walletBalance--tokens
[wallet]=
"wallet"
class=
"m-shadowboxLayout__body"
*ngIf=
"activeCurrencyId === 'tokens'"
></m-walletBalance--tokens>
...
...
This diff is collapsed.
src/app/modules/wallet/v2/dashboard.component.ts
View file @
c45fd44f
...
...
@@ -22,8 +22,8 @@ import { ShadowboxHeaderTab } from '../../../interfaces/dashboard';
export
class
WalletDashboardComponent
implements
OnInit
,
OnDestroy
{
menu
:
Menu
=
sidebarMenu
;
paramsSubscription
:
Subscription
;
wallet
;
currencies
:
ShadowboxHeaderTab
[];
activeCurrencyId
:
string
;
activeViewId
:
string
;
...
...
@@ -41,6 +41,8 @@ export class WalletDashboardComponent implements OnInit, OnDestroy {
btc
:
[{
id
:
'
settings
'
,
label
:
'
Settings
'
}],
};
currencies
:
ShadowboxHeaderTab
[]
=
[];
constructor
(
protected
walletService
:
WalletDashboardService
,
protected
session
:
Session
,
...
...
@@ -57,7 +59,8 @@ export class WalletDashboardComponent implements OnInit, OnDestroy {
}
this
.
title
.
setTitle
(
'
Wallet
'
);
this
.
currencies
=
this
.
walletService
.
getCurrencySubtotals
();
this
.
wallet
=
this
.
walletService
.
getWallet
();
console
.
log
(
'
888wallet
'
,
this
.
wallet
);
this
.
route
.
paramMap
.
subscribe
((
params
:
ParamMap
)
=>
{
this
.
activeCurrencyId
=
params
.
get
(
'
currency
'
);
...
...
@@ -74,6 +77,23 @@ export class WalletDashboardComponent implements OnInit, OnDestroy {
this
.
detectChanges
();
});
this
.
setCurrencies
();
this
.
detectChanges
();
}
setCurrencies
()
{
const
headerCurrencies
=
[
'
tokens
'
,
'
usd
'
,
'
eth
'
,
'
btc
'
];
headerCurrencies
.
forEach
(
currency
=>
{
const
headerTab
:
ShadowboxHeaderTab
=
{
id
:
currency
,
label
:
this
.
wallet
[
currency
].
label
,
unit
:
this
.
wallet
[
currency
].
unit
,
};
if
(
currency
!==
'
btc
'
)
{
headerTab
.
value
=
this
.
wallet
[
currency
].
balance
;
}
this
.
currencies
.
push
(
headerTab
);
});
}
ngOnDestroy
()
{
...
...
This diff is collapsed.
src/app/modules/wallet/v2/dashboard.service.ts
View file @
c45fd44f
import
{
Injectable
}
from
'
@angular/core
'
;
import
{
BehaviorSubject
,
Observable
,
combineLatest
,
of
}
from
'
rxjs
'
;
import
{
map
,
distinctUntilChanged
,
switchMap
,
tap
,
catchError
,
}
from
'
rxjs/operators
'
;
// import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
import
{
MindsHttpClient
}
from
'
../../../common/api/client.service
'
;
// import { ShadowboxHeaderTab } from '../../../interfaces/dashboard';
import
fakeData
from
'
./fake-data
'
;
import
{
Response
,
UserState
,
ShadowboxHeaderTab
,
}
from
'
../../../interfaces/dashboard
'
;
import
{
Web3WalletService
}
from
'
../../blockchain/web3-wallet.service
'
;
import
{
TokenContractService
}
from
'
../../blockchain/contracts/token-contract.service
'
;
import
*
as
BN
from
'
bn.js
'
;
@
Injectable
()
export
class
WalletDashboardService
{
constructor
(
private
http
:
MindsHttpClient
)
{
// this.loadFromRemote();
walletLoaded
:
boolean
=
false
;
totalTokens
=
0
;
wallet
:
any
=
{
tokens
:
{
label
:
'
Tokens
'
,
unit
:
'
tokens
'
,
balance
:
0
,
address
:
null
,
},
offchain
:
{
label
:
'
Off-chain
'
,
unit
:
'
tokens
'
,
balance
:
0
,
address
:
'
offchain
'
,
},
onchain
:
{
label
:
'
On-chain
'
,
unit
:
'
tokens
'
,
balance
:
0
,
address
:
null
,
},
receiver
:
{
label
:
'
Receiver
'
,
unit
:
'
tokens
'
,
balance
:
0
,
address
:
null
,
},
usd
:
{
label
:
'
USD
'
,
unit
:
'
usd
'
,
balance
:
0
,
address
:
null
,
},
eth
:
{
label
:
'
Ether
'
,
unit
:
'
eth
'
,
balance
:
0
,
address
:
null
,
},
btc
:
{
label
:
'
Bitcoin
'
,
unit
:
'
btc
'
,
balance
:
0
,
address
:
null
,
},
};
constructor
(
private
client
:
MindsHttpClient
,
protected
web3Wallet
:
Web3WalletService
,
protected
tokenContract
:
TokenContractService
)
{}
getWallet
()
{
this
.
getTokenAccounts
();
this
.
getStripeAccount
();
this
.
getEthAccount
();
// this.wallet = fakeData.wallet;
this
.
walletLoaded
=
true
;
return
this
.
wallet
;
}
getTokenChartData
(
activeTimespan
)
{
return
fakeData
.
visualisation
;
async
getTokenAccounts
()
{
await
this
.
loadOffchainAndReceiver
();
await
this
.
loadOnchain
();
}
getCurrencySubtotals
()
{
const
currencySubtotals
:
ShadowboxHeaderTab
[]
=
[
{
id
:
'
tokens
'
,
label
:
'
Tokens
'
,
unit
:
'
tokens
'
,
},
{
id
:
'
usd
'
,
label
:
'
USD
'
,
unit
:
'
usd
'
,
},
{
id
:
'
eth
'
,
label
:
'
Ether
'
,
unit
:
'
eth
'
,
},
{
id
:
'
btc
'
,
label
:
'
Bitcoin
'
,
},
];
currencySubtotals
[
0
].
value
=
this
.
getTokenSubtotal
();
currencySubtotals
[
1
].
value
=
this
.
getUsdSubtotal
();
currencySubtotals
[
2
].
value
=
this
.
getEthSubtotal
();
return
currencySubtotals
;
async
loadOffchainAndReceiver
()
{
try
{
const
response
:
any
=
await
this
.
client
.
get
(
`api/v2/blockchain/wallet/balance`
);
if
(
response
&&
response
.
addresses
)
{
this
.
totalTokens
=
response
.
balance
;
response
.
addresses
.
forEach
(
address
=>
{
if
(
address
.
label
===
'
Offchain
'
)
{
this
.
wallet
.
offchain
.
balance
=
address
.
balance
;
}
else
if
(
address
.
label
===
'
Receiver
'
)
{
this
.
wallet
.
onchain
.
balance
=
address
.
balance
;
this
.
wallet
.
receiver
.
balance
=
address
.
balance
;
this
.
wallet
.
receiver
.
address
=
address
.
address
;
}
});
}
else
{
console
.
error
(
'
No data
'
);
}
}
catch
(
e
)
{
console
.
error
(
e
);
}
}
private
getTokenSubtotal
()
{
// see WalletBalanceTokensComponent loadLocal(), loadRemote()
return
2167.457
;
async
loadOnchain
()
{
try
{
const
address
=
await
this
.
web3Wallet
.
getCurrentWallet
();
if
(
!
address
)
{
return
;
}
this
.
wallet
.
onchain
.
address
=
address
;
if
(
this
.
wallet
.
receiver
.
address
===
address
)
{
return
;
// don't re-add onchain to totalTokens
}
const
onchainBalance
=
await
this
.
tokenContract
.
balanceOf
(
address
);
this
.
wallet
.
onchain
.
balance
=
onchainBalance
[
0
].
toString
();
this
.
totalTokens
=
new
BN
(
this
.
totalTokens
).
add
(
onchainBalance
[
0
]);
}
catch
(
e
)
{
console
.
log
(
e
);
}
}
private
getUsdSubtotal
()
{
// get from Mark after Stripe update
return
13577
;
async
getEthAccount
()
{
const
address
=
await
this
.
web3Wallet
.
getCurrentWallet
();
if
(
!
address
)
{
return
;
}
this
.
wallet
.
eth
.
address
=
address
;
const
ethBalance
=
await
this
.
web3Wallet
.
getBalance
(
address
);
if
(
ethBalance
)
{
this
.
wallet
.
eth
.
balance
=
ethBalance
;
}
}
async
getStripeAccount
()
{
const
stripeAccount
=
<
any
>
(
await
this
.
client
.
get
(
'
api/v2/payments/stripe/connect
'
)
);
if
(
stripeAccount
&&
stripeAccount
.
totalBalance
)
{
this
.
wallet
.
usd
.
value
=
stripeAccount
.
totalBalance
.
amount
+
stripeAccount
.
pendingBalance
.
amount
;
}
return
stripeAccount
;
}
async
getStripeTransactions
()
{
const
{
transactions
}
=
<
any
>
(
await
this
.
client
.
get
(
'
api/v2/payments/stripe/transactions
'
)
);
return
transactions
;
}
async
getTokenPayoutOverview
():
Promise
<
any
>
{
try
{
const
result
:
any
=
await
this
.
client
.
get
(
`api/v2/blockchain/contributions/overview`
);
return
result
;
}
catch
(
e
)
{
console
.
error
(
e
);
}
}
async
hasMetamask
():
Promise
<
boolean
>
{
const
isLocal
:
any
=
await
this
.
web3Wallet
.
isLocal
();
return
Boolean
(
isLocal
);
}
// TODOOJM bucket endpoint needed
getTokenChart
(
activeTimespan
)
{
return
fakeData
.
visualisation
;
}
private
getEthSubtotal
()
{
// see WalletBalanceTokensComponent loadEth()
return
15.3570957
;
// TODOOJM tx/contribution endpoint needed
getTokenTransactionTable
()
{
return
fakeData
.
token_transactions
;
}
}
This diff is collapsed.
src/app/modules/wallet/v2/fake-data.ts
View file @
c45fd44f
const
fakeData
=
{
wallet
:
{
tokens
:
{
label
:
'
Tokens
'
,
unit
:
'
tokens
'
,
balance
:
'
777123456789987654321
'
,
address
:
null
,
},
offchain
:
{
label
:
'
Off-chain
'
,
unit
:
'
tokens
'
,
balance
:
'
222000000000000000000
'
,
address
:
'
offchain
'
,
},
onchain
:
{
label
:
'
On-chain
'
,
unit
:
'
tokens
'
,
balance
:
'
333123956789987654321
'
,
address
:
'
0x7aA1A2a94c799f0124B6Bf8481D529BDa844498D
'
,
},
receiver
:
{
label
:
'
Receiver
'
,
unit
:
'
tokens
'
,
balance
:
'
000123456789987654321
'
,
address
:
'
0x8aA1A2a94c799f0124B6Bf8481D529BDa844498D
'
,
},
usd
:
{
label
:
'
USD
'
,
unit
:
'
usd
'
,
balance
:
2550
,
address
:
null
,
},
eth
:
{
label
:
'
Ether
'
,
unit
:
'
eth
'
,
balance
:
'
1111595995595595595595
'
,
address
:
'
0x7aA1A2a94c799f0124B6Bf8481D529BDa844498D
'
,
},
btc
:
{
label
:
'
Bitcoin
'
,
unit
:
'
btc
'
,
balance
:
0
,
address
:
null
,
},
},
// balances: {
// tokens: '777123456789987654321',
// offchain: '222123456789987654321',
// onchain: '333123456789987654321',
// receiver: '000123456789987654321',
// eth: '111123456789987654321',
// usd: 250,
// },
// addresses: {
// receiver: '0x8aA1A2a94c799f0124B6Bf8481D529BDa844498D',
// onchain: '0x7aA1A2a94c799f0124B6Bf8481D529BDa844498D',
// eth: '0x7aA1A2a94c799f0124B6Bf8481D529BDa844498D',
// },
visualisation
:
{
type
:
'
chart
'
,
unit
:
'
tokens
'
,
...
...
@@ -70,7 +127,6 @@ const fakeData = {
],
},
token_transactions
:
{
current_total
:
25.0
,
filters
:
[
{
id
:
'
transaction_types
'
,
...
...
This diff is collapsed.
Please
register
or
sign in
to comment