Skip to content

Commit 547a713

Browse files
authored
feat: f05 balance manager (#682)
* f05 bmgr * f05 bmgr fixes * fix f05 bm build * gofmt
1 parent 913022c commit 547a713

File tree

4 files changed

+186
-3
lines changed

4 files changed

+186
-3
lines changed

tasks/balancemgr/handlers_f05.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package balancemgr
2+
3+
import (
4+
"context"
5+
6+
"golang.org/x/xerrors"
7+
8+
"github.com/filecoin-project/go-address"
9+
"github.com/filecoin-project/go-state-types/abi"
10+
"github.com/filecoin-project/go-state-types/big"
11+
12+
"github.com/filecoin-project/curio/harmony/harmonydb"
13+
"github.com/filecoin-project/curio/harmony/harmonytask"
14+
15+
"github.com/filecoin-project/lotus/api"
16+
"github.com/filecoin-project/lotus/chain/actors"
17+
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
18+
"github.com/filecoin-project/lotus/chain/types"
19+
)
20+
21+
func (b *BalanceMgrTask) adderF05(ctx context.Context, taskFunc harmonytask.AddTaskFunc, addr *balanceManagerAddress) error {
22+
marketBalance, err := b.chain.StateMarketBalance(ctx, addr.SubjectAddress, types.EmptyTSK)
23+
if err != nil {
24+
return xerrors.Errorf("getting market balance: %w", err)
25+
}
26+
27+
sourceBalance, err := b.chain.StateGetActor(ctx, addr.SubjectAddress, types.EmptyTSK)
28+
if err != nil {
29+
return xerrors.Errorf("getting source balance: %w", err)
30+
}
31+
32+
addr.SubjectBalance = big.Sub(marketBalance.Escrow, marketBalance.Locked)
33+
addr.SecondBalance = sourceBalance.Balance
34+
35+
var shouldCreateTask bool
36+
switch addr.ActionType {
37+
case "requester":
38+
shouldCreateTask = addr.SubjectBalance.LessThan(addr.LowWatermarkFilBalance)
39+
}
40+
41+
if shouldCreateTask {
42+
taskFunc(func(taskID harmonytask.TaskID, tx *harmonydb.Tx) (shouldCommit bool, seriousError error) {
43+
// check that address.ID has active_task_id = null, set the task ID, set last_ to null
44+
n, err := tx.Exec(`
45+
UPDATE balance_manager_addresses
46+
SET active_task_id = $1, last_msg_cid = NULL, last_msg_sent_at = NULL, last_msg_landed_at = NULL
47+
WHERE id = $2 AND active_task_id IS NULL AND (last_msg_cid IS NULL OR last_msg_landed_at IS NOT NULL)
48+
`, taskID, addr.ID)
49+
if err != nil {
50+
return false, xerrors.Errorf("updating balance manager address: %w", err)
51+
}
52+
53+
return n > 0, nil
54+
})
55+
}
56+
return nil
57+
}
58+
59+
func (b *BalanceMgrTask) doF05(ctx context.Context, taskID harmonytask.TaskID, addr *balanceManagerAddress) (bool, error) {
60+
log.Infow("balancemgr f05 Do",
61+
"id", addr.ID,
62+
"subject", addr.SubjectAddress,
63+
"low", types.FIL(addr.LowWatermarkFilBalance),
64+
"high", types.FIL(addr.HighWatermarkFilBalance))
65+
66+
marketBalance, err := b.chain.StateMarketBalance(ctx, addr.SubjectAddress, types.EmptyTSK)
67+
if err != nil {
68+
return false, xerrors.Errorf("getting market balance: %w", err)
69+
}
70+
71+
sourceBalance, err := b.chain.StateGetActor(ctx, addr.SubjectAddress, types.EmptyTSK)
72+
if err != nil {
73+
return false, xerrors.Errorf("getting source balance: %w", err)
74+
}
75+
76+
addr.SubjectBalance = big.Sub(marketBalance.Escrow, marketBalance.Locked)
77+
addr.SecondBalance = types.BigInt(sourceBalance.Balance)
78+
79+
// calculate amount to send (based on latest chain balance)
80+
var amount types.BigInt
81+
var to address.Address
82+
var shouldSend bool
83+
84+
if addr.ActionType != "requester" {
85+
return false, xerrors.Errorf("action type is not requester: %s", addr.ActionType)
86+
}
87+
88+
if addr.SubjectBalance.LessThan(addr.LowWatermarkFilBalance) {
89+
amount = types.BigSub(addr.HighWatermarkFilBalance, addr.SubjectBalance)
90+
to = addr.SubjectAddress
91+
shouldSend = true
92+
}
93+
94+
if !shouldSend {
95+
log.Infow("balance within watermarks, no action needed",
96+
"subject", addr.SubjectAddress,
97+
"balance", types.FIL(addr.SubjectBalance),
98+
"low", types.FIL(addr.LowWatermarkFilBalance),
99+
"high", types.FIL(addr.HighWatermarkFilBalance))
100+
101+
_, err = b.db.Exec(ctx, `
102+
UPDATE balance_manager_addresses
103+
SET active_task_id = NULL, last_action = NOW()
104+
WHERE id = $1
105+
`, addr.ID)
106+
if err != nil {
107+
return false, xerrors.Errorf("clearing task id: %w", err)
108+
}
109+
return true, nil
110+
}
111+
112+
params, err := actors.SerializeParams(&addr.SubjectAddress)
113+
if err != nil {
114+
return false, xerrors.Errorf("failed to serialize miner address: %w", err)
115+
}
116+
117+
maxfee, err := types.ParseFIL("0.05 FIL")
118+
if err != nil {
119+
return false, xerrors.Errorf("failed to parse max fee: %w", err)
120+
}
121+
122+
msp := &api.MessageSendSpec{
123+
MaxFee: abi.TokenAmount(maxfee),
124+
}
125+
126+
msg := &types.Message{
127+
To: market.Address,
128+
From: addr.SecondAddress,
129+
Value: amount,
130+
Method: market.Methods.AddBalance,
131+
Params: params,
132+
}
133+
134+
msgCid, err := b.sender.Send(ctx, msg, msp, "balancemgr-f05")
135+
if err != nil {
136+
return false, xerrors.Errorf("failed to send message: %w", err)
137+
}
138+
139+
_, err = b.db.Exec(ctx, `INSERT INTO message_waits (signed_message_cid) VALUES ($1)`, msgCid)
140+
if err != nil {
141+
return false, xerrors.Errorf("inserting into message_waits: %w", err)
142+
}
143+
144+
_, err = b.db.Exec(ctx, `
145+
UPDATE balance_manager_addresses
146+
SET last_msg_cid = $2,
147+
last_msg_sent_at = NOW(),
148+
last_msg_landed_at = NULL,
149+
active_task_id = NULL
150+
WHERE id = $1
151+
`, addr.ID, msgCid.String())
152+
if err != nil {
153+
return false, xerrors.Errorf("updating message cid: %w", err)
154+
}
155+
156+
log.Infow("sent balance management message",
157+
"from", addr.SecondAddress,
158+
"to", to,
159+
"subjectType", "f05",
160+
"amount", types.FIL(amount),
161+
"msgCid", msgCid,
162+
"actionType", addr.ActionType)
163+
164+
return true, nil
165+
}

tasks/balancemgr/task_balancemgr.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ func NewBalanceMgrTask(db *harmonydb.DB, chain api.FullNode, pcs *chainsched.Cur
126126
err = t.adderWallet(ctx, taskFunc, addr)
127127
case "proofshare":
128128
err = t.adderProofshare(ctx, taskFunc, addr)
129+
case "f05":
130+
err = t.adderF05(ctx, taskFunc, addr)
129131
default:
130132
log.Warnw("unknown subject type", "type", addr.SubjectType)
131133
continue
@@ -163,8 +165,8 @@ func (b *BalanceMgrTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask
163165
return nil, xerrors.Errorf("getting subject type: %w", err)
164166
}
165167

166-
if subjectType == "wallet" ||
167-
subjectType == "proofshare" {
168+
switch subjectType {
169+
case "wallet", "proofshare", "f05":
168170
return &id, nil
169171
}
170172
}
@@ -232,6 +234,8 @@ func (b *BalanceMgrTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (
232234
return b.doWallet(ctx, taskID, addr)
233235
case "proofshare":
234236
return b.doProofshare(ctx, taskID, addr)
237+
case "f05":
238+
return b.doF05(ctx, taskID, addr)
235239
default:
236240
return false, xerrors.Errorf("unknown subject type: %s", addr.SubjectType)
237241
}

web/api/webrpc/balance_manager.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ func (a *WebRPC) BalanceMgrRuleAdd(ctx context.Context, subject, second, actionT
128128
switch actionType {
129129
case "requester":
130130
case "active-provider":
131+
case "f05":
131132
default:
132133
return xerrors.Errorf("invalid action type: %s", actionType)
133134
}
@@ -141,6 +142,8 @@ func (a *WebRPC) BalanceMgrRuleAdd(ctx context.Context, subject, second, actionT
141142
// For proofshare, subject == second and action is always requester
142143
actionType = "requester"
143144
second = subject
145+
case "f05":
146+
actionType = "requester"
144147
default:
145148
return xerrors.Errorf("invalid subject type: %s", subjectType)
146149
}

web/static/pages/wallet/balance-manager.mjs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ class BalanceManager extends LitElement {
9292
this.newHigh = '';
9393
}
9494

95+
startAddF05() {
96+
this.adding = true;
97+
this.newSubjectType = 'f05';
98+
this.newSubject = '';
99+
this.newSecond = '';
100+
this.newAction = 'requester';
101+
this.newLow = '';
102+
this.newHigh = '';
103+
}
104+
95105
cancelAdd() {
96106
this.adding = false;
97107
}
@@ -149,6 +159,7 @@ class BalanceManager extends LitElement {
149159
<h2>Balance-Manager Rules</h2>
150160
<button class="btn btn-primary btn-sm mb-2" @click=${this.startAddWallet}>Add Wallet Rule</button>
151161
<button class="btn btn-primary btn-sm mb-2" @click=${this.startAddProofshare}>Add SnarkMarket Client Rule</button>
162+
<button class="btn btn-primary btn-sm mb-2" @click=${this.startAddF05}>Add F05 Rule</button>
152163
${this.adding
153164
? html`
154165
<div class="card card-body bg-dark text-light mb-3">
@@ -157,7 +168,7 @@ class BalanceManager extends LitElement {
157168
<label class="form-label mb-0">Subject</label>
158169
<input class="form-control form-control-sm" .value=${this.newSubject} @input=${(e) => (this.newSubject = e.target.value)} />
159170
</div>
160-
${this.newSubjectType === 'wallet' ? html`
171+
${(this.newSubjectType === 'wallet' || this.newSubjectType === 'f05') ? html`
161172
<div class="col-md-2">
162173
<label class="form-label mb-0">Second</label>
163174
<input class="form-control form-control-sm" .value=${this.newSecond} @input=${(e) => (this.newSecond = e.target.value)} />

0 commit comments

Comments
 (0)