Skip to content

Commit 56c43a1

Browse files
feat: asi reconcilliation transfer (#344)
1 parent 07ff5ac commit 56c43a1

File tree

1 file changed

+129
-33
lines changed

1 file changed

+129
-33
lines changed

cmd/fetchd/cmd/genasiupgrade.go

Lines changed: 129 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
11
package cmd
22

33
import (
4+
"bytes"
5+
_ "embed"
6+
"encoding/csv"
47
"encoding/json"
58
"fmt"
69
"github.com/btcsuite/btcutil/bech32"
710
"github.com/cosmos/cosmos-sdk/client"
811
"github.com/cosmos/cosmos-sdk/client/flags"
912
"github.com/cosmos/cosmos-sdk/server"
1013
sdk "github.com/cosmos/cosmos-sdk/types"
14+
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
1115
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
1216
"github.com/cosmos/cosmos-sdk/x/genutil"
1317
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
1418
ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
15-
ibc_core "github.com/cosmos/ibc-go/v3/modules/core/24-host"
19+
ibccore "github.com/cosmos/ibc-go/v3/modules/core/24-host"
1620
"github.com/spf13/cobra"
1721
"github.com/tendermint/tendermint/types"
22+
"log"
1823
"regexp"
24+
"strconv"
1925
"strings"
2026
)
2127

2228
const (
2329
BridgeContractAddress = "fetch1qxxlalvsdjd07p07y3rc5fu6ll8k4tmetpha8n"
2430
NewBridgeContractAdmin = "fetch15p3rl5aavw9rtu86tna5lgxfkz67zzr6ed4yhw"
2531

26-
IbcWithdrawAddress = "fetch1rhrlzsx9z865dqen8t4v47r99dw6y4va4uph0x" /* "asi1rhrlzsx9z865dqen8t4v47r99dw6y4vaw76rd9" */
32+
IbcWithdrawAddress = "fetch1rhrlzsx9z865dqen8t4v47r99dw6y4va4uph0x" /* "asi1rhrlzsx9z865dqen8t4v47r99dw6y4vaw76rd9" */
33+
ReconciliationWithdrawAddress = "fetch1rhrlzsx9z865dqen8t4v47r99dw6y4va4uph0x"
2734

2835
flagNewDescription = "new-description"
2936
Bech32Chars = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
@@ -40,11 +47,13 @@ const (
4047
NewChainId = "asi-1"
4148
NewDescription = "ASI Token"
4249

43-
OldBaseDenom = "fet"
4450
OldDenom = "afet"
4551
OldAddrPrefix = "fetch"
4652
)
4753

54+
//go:embed reconciliation_data.csv
55+
var reconciliationData []byte
56+
4857
// ASIGenesisUpgradeCmd returns replace-genesis-values cobra Command.
4958
func ASIGenesisUpgradeCmd(defaultNodeHome string) *cobra.Command {
5059
cmd := &cobra.Command{
@@ -87,6 +96,11 @@ func ASIGenesisUpgradeCmd(defaultNodeHome string) *cobra.Command {
8796
return err
8897
}
8998

99+
// withdraw balances from reconciliation addresses
100+
if err = ASIGenesisUpgradeWithdrawReconciliationBalances(jsonData); err != nil {
101+
return err
102+
}
103+
90104
// replace denom across the genesis file
91105
ASIGenesisUpgradeReplaceDenom(jsonData)
92106

@@ -234,18 +248,15 @@ func replaceAddresses(addressTypePrefix string, jsonData map[string]interface{},
234248
func ASIGenesisUpgradeWithdrawIBCChannelsBalances(jsonData map[string]interface{}) error {
235249
bank := jsonData[banktypes.ModuleName].(map[string]interface{})
236250
balances := bank["balances"].([]interface{})
237-
balanceMap, err := getGenesisBalancesMap(balances)
238-
if err != nil {
239-
return err
240-
}
251+
balanceMap := getGenesisBalancesMap(balances)
241252

242253
withdrawalBalanceIdx, ok := (*balanceMap)[IbcWithdrawAddress]
243254
if !ok {
244255
fmt.Println("failed to find Ibc withdrawal address in genesis balances - have addresses already been converted?")
245256
return nil
246257
}
247258

248-
ibc := jsonData[ibc_core.ModuleName].(map[string]interface{})
259+
ibc := jsonData[ibccore.ModuleName].(map[string]interface{})
249260
channelGenesis := ibc["channel_genesis"].(map[string]interface{})
250261
ibcChannels := channelGenesis["channels"].([]interface{})
251262

@@ -273,13 +284,113 @@ func ASIGenesisUpgradeWithdrawIBCChannelsBalances(jsonData map[string]interface{
273284
balances[withdrawalBalanceIdx].(map[string]interface{})["coins"] = getInterfaceSliceFromCoins(newWithdrawalBalanceCoins)
274285

275286
// zero out the channel balance
276-
balances[balanceIdx] = nil
287+
balances[balanceIdx].(map[string]interface{})["coins"] = []interface{}{}
277288
}
278289

279290
return nil
280291
}
281292

282-
func ASIGenesisUpgradeWithdrawReconciliationBalances() {}
293+
func getGenesisAccountSequenceMap(accounts []interface{}) *map[string]int {
294+
const ModuleAccount = "/cosmos.auth.v1beta1.ModuleAccount"
295+
accountMap := make(map[string]int)
296+
297+
for _, acc := range accounts {
298+
accType := acc.(map[string]interface{})["@type"]
299+
300+
accData := acc
301+
if accType == ModuleAccount {
302+
accData = acc.(map[string]interface{})["base_account"]
303+
}
304+
305+
addr := accData.(map[string]interface{})["address"].(string)
306+
sequence := accData.(map[string]interface{})["sequence"].(string)
307+
308+
sequenceInt, ok := strconv.Atoi(sequence)
309+
if ok != nil {
310+
panic("getGenesisAccountSequenceMap: failed to convert sequence to int")
311+
}
312+
accountMap[addr] = sequenceInt
313+
}
314+
315+
return &accountMap
316+
}
317+
318+
func ASIGenesisUpgradeWithdrawReconciliationBalances(jsonData map[string]interface{}) error {
319+
bank := jsonData[banktypes.ModuleName].(map[string]interface{})
320+
balances := bank["balances"].([]interface{})
321+
322+
balanceMap := getGenesisBalancesMap(balances)
323+
324+
auth := jsonData[authtypes.ModuleName].(map[string]interface{})
325+
accounts := auth["accounts"].([]interface{})
326+
accountSequenceMap := getGenesisAccountSequenceMap(accounts)
327+
328+
fileData := reconciliationData
329+
r := csv.NewReader(bytes.NewReader(fileData))
330+
items, err := r.ReadAll()
331+
if err != nil {
332+
log.Fatalf("Error reading reconciliation data: %s", err)
333+
}
334+
335+
reconciliationBalanceIdx, ok := (*balanceMap)[ReconciliationWithdrawAddress]
336+
if !ok {
337+
return fmt.Errorf("no genesis match for reconciliation address: %s", ReconciliationWithdrawAddress)
338+
}
339+
340+
for _, row := range items {
341+
addr := row[2]
342+
343+
//_ = row[3] balance from CSV
344+
345+
accSequence, ok := (*accountSequenceMap)[addr]
346+
if !ok {
347+
return fmt.Errorf("no genesis match for reconciliation address: %s", addr)
348+
}
349+
350+
balanceIdx, ok := (*balanceMap)[addr]
351+
if !ok {
352+
continue
353+
}
354+
355+
accBalance := balances[balanceIdx]
356+
accBalanceCoins := getCoinsFromInterfaceSlice(accBalance)
357+
358+
reconciliationBalance := balances[reconciliationBalanceIdx]
359+
reconciliationBalanceCoins := getCoinsFromInterfaceSlice(reconciliationBalance)
360+
361+
// check if the reconciliation address is still dormant and contains funds
362+
if accSequence != 0 || !accBalanceCoins.IsAllPositive() {
363+
continue
364+
}
365+
366+
// add reconciliation account balance to withdrawal balance
367+
newReconciliationBalanceCoins := reconciliationBalanceCoins.Add(accBalanceCoins...)
368+
reconciliationBalance.(map[string]interface{})["coins"] = getInterfaceSliceFromCoins(newReconciliationBalanceCoins)
369+
370+
// zero out the reconciliation account balance
371+
balances[balanceIdx].(map[string]interface{})["coins"] = []interface{}{}
372+
}
373+
return nil
374+
}
375+
376+
func convertAddressToASI(addr string, addressPrefix string) (string, error) {
377+
_, decodedAddrData, err := bech32.Decode(addr)
378+
if err != nil {
379+
return "", err
380+
}
381+
382+
newAddress, err := bech32.Encode(NewAddrPrefix+addressPrefix, decodedAddrData)
383+
if err != nil {
384+
return "", err
385+
}
386+
387+
err = sdk.VerifyAddressFormat(decodedAddrData)
388+
if err != nil {
389+
return "", err
390+
}
391+
392+
return newAddress, nil
393+
}
283394

284395
func crawlJson(key string, value interface{}, idx int, strHandler func(string, interface{}, int) interface{}) interface{} {
285396
switch val := value.(type) {
@@ -299,34 +410,19 @@ func crawlJson(key string, value interface{}, idx int, strHandler func(string, i
299410
return value
300411
}
301412

302-
func getGenesisBalancesMap(balances []interface{}) (*map[string]int, error) {
413+
func getGenesisBalancesMap(balances []interface{}) *map[string]int {
303414
balanceMap := make(map[string]int)
304415

305416
for i, balance := range balances {
306-
addr := balance.(map[string]interface{})["address"].(string)
307-
balanceMap[addr] = i
308-
}
309-
310-
return &balanceMap, nil
311-
}
312-
313-
func convertAddressToASI(addr string, addressTypePrefix string) (string, error) {
314-
_, decodedAddrData, err := bech32.Decode(addr)
315-
if err != nil {
316-
return "", fmt.Errorf("failed to decode address: %w", err)
317-
}
318-
319-
err = sdk.VerifyAddressFormat(decodedAddrData)
320-
if err != nil {
321-
return "", fmt.Errorf("failed to verify address format: %w", err)
322-
}
323-
324-
newAddress, err := bech32.Encode(NewAddrPrefix+addressTypePrefix, decodedAddrData)
325-
if err != nil {
326-
return "", fmt.Errorf("failed to encode new address: %w", err)
417+
addr := balance.(map[string]interface{})["address"]
418+
if addr == nil {
419+
fmt.Println(balance)
420+
}
421+
addrStr := addr.(string)
422+
balanceMap[addrStr] = i
327423
}
328424

329-
return newAddress, nil
425+
return &balanceMap
330426
}
331427

332428
func getCoinsFromInterfaceSlice(data interface{}) sdk.Coins {

0 commit comments

Comments
 (0)