diff --git a/bsc/wbnb.go b/bsc/wbnb.go index 20fc033..2a5e4fc 100644 --- a/bsc/wbnb.go +++ b/bsc/wbnb.go @@ -5,7 +5,6 @@ import ( "git.lehouerou.net/laurent/evm" "git.lehouerou.net/laurent/evm/bsc/contracts" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" "github.com/shopspring/decimal" @@ -17,12 +16,16 @@ type WBNB struct { contract *contracts.WBnb } -func NewWBNB(address string, client evm.Client) (*WBNB, error) { - t, err := evm.NewToken(client, common.HexToAddress(address)) +func NewWBNB(client evm.Client) (*WBNB, error) { + address, err := client.TokenService().TokenAddressBySymbol("WBNB") + if err != nil { + return nil, errors.Wrap(err, "getting wbnb address") + } + t, err := evm.NewToken(client, address) if err != nil { return nil, errors.Wrap(err, "init token contract") } - c, err := contracts.NewWBnb(common.HexToAddress(address), client) + c, err := contracts.NewWBnb(address, client) if err != nil { return nil, errors.Wrap(err, "init wbnb contract") } diff --git a/polycat/catpair.go b/polycat/catpair.go new file mode 100644 index 0000000..0e88778 --- /dev/null +++ b/polycat/catpair.go @@ -0,0 +1,64 @@ +package polycat + +import ( + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polycat/contracts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type CatPair struct { + evm.Token + paircontract *contracts.CatPair +} + +func NewCatPair(client evm.Client, address common.Address) (*CatPair, error) { + t, err := client.TokenService().TokenByAddress(address) + if err != nil { + return nil, errors.Wrap(err, "init contract") + } + + pc, err := contracts.NewCatPair(address, client) + if err != nil { + return nil, errors.Wrap(err, "init pair contract") + } + + return &CatPair{ + Token: t, + paircontract: pc, + }, nil +} + +func (p *CatPair) GetReserves() (decimal.Decimal, decimal.Decimal, error) { + res, err := p.paircontract.GetReserves(&bind.CallOpts{}) + if err != nil { + return decimal.Zero, decimal.Zero, errors.Wrap(err, "calling pair contract") + } + return p.ValueFromBigInt(res.Reserve0), p.ValueFromBigInt(res.Reserve1), nil +} + +func (p *CatPair) getToken0() (evm.Token, error) { + t0address, err := p.paircontract.Token0(&bind.CallOpts{}) + if err != nil { + return nil, errors.Wrap(err, "getting token0 address") + } + t0, err := p.Client().TokenService().TokenByAddress(t0address) + if err != nil { + return nil, errors.Wrap(err, "getting token0 contract") + } + return t0, nil +} + +func (p *CatPair) getToken1() (evm.Token, error) { + t1address, err := p.paircontract.Token0(&bind.CallOpts{}) + if err != nil { + return nil, errors.Wrap(err, "getting token1 address") + } + t1, err := p.Client().TokenService().TokenByAddress(t1address) + if err != nil { + return nil, errors.Wrap(err, "getting token1 contract") + } + return t1, nil +} diff --git a/polycat/catrouter.go b/polycat/catrouter.go new file mode 100644 index 0000000..feb4ed8 --- /dev/null +++ b/polycat/catrouter.go @@ -0,0 +1,18 @@ +package polycat + +import ( + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polycat/contracts" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" +) + +const CatRouterAddress = "0x94930a328162957FF1dd48900aF67B5439336cBD" + +func NewCatRouterService(c evm.Client) (*evm.UniswapRouter, error) { + contract, err := contracts.NewCatRouter(common.HexToAddress(CatRouterAddress), c) + if err != nil { + return nil, errors.Wrap(err, "init contract") + } + return evm.NewUniswapRouter("polycat", c, contract), nil +} diff --git a/polycat/masterchef.go b/polycat/masterchef.go new file mode 100644 index 0000000..cfc18e8 --- /dev/null +++ b/polycat/masterchef.go @@ -0,0 +1,46 @@ +package polycat + +import ( + "context" + "math/big" + + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polycat/contracts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +const ( + MasterchefAddress = "0x8CFD1B9B7478E7B0422916B72d1DB6A9D513D734" + DepositReferer = "0" +) + +type MasterchefService struct { + client evm.Client + contract *contracts.Masterchef +} + +func NewMasterchefService(c evm.Client) (*MasterchefService, error) { + contract, err := contracts.NewMasterchef(common.HexToAddress(MasterchefAddress), c) + if err != nil { + return nil, errors.Wrap(err, "init contract") + } + return &MasterchefService{ + contract: contract, + client: c, + }, nil +} + +func (s *MasterchefService) Harvest(ctx context.Context, poolid int, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.Deposit(options.TransactOpts, big.NewInt(int64(poolid)), big.NewInt(0), common.HexToAddress(DepositReferer)) + }, opts...) +} + +func (s *MasterchefService) Deposit(ctx context.Context, poolid int, amount decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.Deposit(options.TransactOpts, big.NewInt(int64(poolid)), amount.Shift(18).BigInt(), common.HexToAddress(DepositReferer)) + }, opts...) +} diff --git a/polycat/masterchefv2.go b/polycat/masterchefv2.go new file mode 100644 index 0000000..bcadb45 --- /dev/null +++ b/polycat/masterchefv2.go @@ -0,0 +1,84 @@ +package polycat + +import ( + "context" + "math/big" + + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polycat/contracts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +const ( + Masterchefv2Address = "0x4ce9Ae2f5983e19AebF5b8Bae4460f2B9EcE811a" +) + +type Masterchefv2Service struct { + client evm.Client + contract *contracts.MasterChefv2 +} + +func NewMasterchefv2Service(c evm.Client) (*Masterchefv2Service, error) { + contract, err := contracts.NewMasterChefv2(common.HexToAddress(Masterchefv2Address), c) + if err != nil { + return nil, errors.Wrap(err, "init contract") + } + return &Masterchefv2Service{ + contract: contract, + client: c, + }, nil +} + +func (s *Masterchefv2Service) PoolInfo(pid int) (*PoolInfo, error) { + pi, err := s.contract.PoolInfo(&bind.CallOpts{}, big.NewInt(int64(pid))) + if err != nil { + return nil, errors.Wrap(err, "gettting pool info") + } + ui, err := s.contract.UserInfo(&bind.CallOpts{}, big.NewInt(int64(pid)), s.client.PublicAddress()) + if err != nil { + return nil, errors.Wrap(err, "getting user info") + } + pair, err := NewCatPair(s.client, pi.LpToken) + if err != nil { + return nil, errors.Wrap(err, "getting pair contract") + } + return &PoolInfo{ + LpToken: pair, + Balance: pair.ValueFromBigInt(ui.Amount), + TotalDeposited: pair.ValueFromBigInt(pi.TotalDeposited), + }, nil +} + +func (s *Masterchefv2Service) HarvestAll(ctx context.Context, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.HarvestAll(options.TransactOpts) + }, opts...) +} + +func (s *Masterchefv2Service) PendingRewards(pids []int) (decimal.Decimal, error) { + var tot decimal.Decimal + for _, pid := range pids { + pr, err := s.contract.PendingPaw(&bind.CallOpts{}, big.NewInt(int64(pid)), s.client.PublicAddress()) + if err != nil { + return decimal.Zero, errors.Wrapf(err, "getting pending reward for pid %d", pid) + } + tot = tot.Add(decimal.NewFromBigInt(pr, -18)) + } + return tot, nil +} + +func (s *Masterchefv2Service) Deposit(ctx context.Context, pid int, amount decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.Deposit(options.TransactOpts, big.NewInt(int64(pid)), amount.Shift(18).BigInt(), false) + }, opts...) +} + +func (s *Masterchefv2Service) Withdraw(ctx context.Context, pid int, amount decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.Withdraw(options.TransactOpts, big.NewInt(int64(pid)), amount.Shift(18).BigInt(), false) + }, opts...) +} diff --git a/polycat/poolinfo.go b/polycat/poolinfo.go new file mode 100644 index 0000000..cf03a59 --- /dev/null +++ b/polycat/poolinfo.go @@ -0,0 +1,13 @@ +package polycat + +import "github.com/shopspring/decimal" + +type PoolInfo struct { + LpToken *CatPair + Balance decimal.Decimal + TotalDeposited decimal.Decimal +} + +func (pi *PoolInfo) BalanceRatio() decimal.Decimal { + return pi.Balance.Div(pi.TotalDeposited) +} diff --git a/polycat/rewardlocker.go b/polycat/rewardlocker.go new file mode 100644 index 0000000..79e2b4d --- /dev/null +++ b/polycat/rewardlocker.go @@ -0,0 +1,83 @@ +package polycat + +import ( + "context" + "math/big" + + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polycat/contracts" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +const RewardLockerAddress = "0xE0e44d4E7e61f2f4f990f5F4e2408D2187315C94" + +type RewardLockerService struct { + client evm.Client + contract *contracts.RewardLocker +} + +func NewRewardLockerService(c evm.Client) (*RewardLockerService, error) { + contract, err := contracts.NewRewardLocker(common.HexToAddress(RewardLockerAddress), c) + if err != nil { + return nil, errors.Wrap(err, "init contract") + } + return &RewardLockerService{ + contract: contract, + client: c, + }, nil +} + +func (s *RewardLockerService) ClaimAll(ctx context.Context, token common.Address, opts ...evm.ExecutionOption) (evm.Transaction, error) { + schedcount, err := s.contract.NumVestingSchedules(&bind.CallOpts{}, s.client.PublicAddress(), token) + if err != nil { + return nil, errors.Wrap(err, "getting schedule count") + } + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.VestSchedulesInRange(options.TransactOpts, token, big.NewInt(0), decimal.NewFromBigInt(schedcount, 0).Sub(decimal.NewFromInt(1)).BigInt()) + }, opts...) +} + +func (s *RewardLockerService) GetClaimableReward(ctx context.Context, token common.Address) (decimal.Decimal, error) { + scheds, err := s.contract.GetVestingSchedules(&bind.CallOpts{}, s.client.PublicAddress(), token) + if err != nil { + return decimal.Zero, errors.Wrap(err, "getting vesting schedules") + } + var tot decimal.Decimal + block, err := s.client.CurrentBlockNumber(ctx) + if err != nil { + return decimal.Zero, errors.Wrap(err, "getting current block") + } + for _, sched := range scheds { + tot = tot.Add(GetVestingQuantity(sched, block)) + } + return tot, nil +} + +func GetVestingQuantity(sched contracts.IRewardLockerVestingSchedule, block uint64) decimal.Decimal { + if block >= sched.EndBlock { + return decimal.NewFromBigInt(sched.Quantity, -18).Sub(decimal.NewFromBigInt(sched.VestedQuantity, -18)) + } + if block <= sched.StartBlock { + return decimal.Zero + } + + lockduration := sched.EndBlock - sched.StartBlock + passedDuration := block - sched.StartBlock + return decimal.NewFromBigInt(sched.Quantity, -18).Mul(decimal.NewFromInt(int64(passedDuration))).Div(decimal.NewFromInt(int64(lockduration))).Sub(decimal.NewFromBigInt(sched.VestedQuantity, -18)) +} + +func (s *RewardLockerService) GetLockedReward(token common.Address) (decimal.Decimal, error) { + scheds, err := s.contract.GetVestingSchedules(&bind.CallOpts{}, s.client.PublicAddress(), token) + if err != nil { + return decimal.Zero, errors.Wrap(err, "getting vesting schedules") + } + var tot decimal.Decimal + for _, sched := range scheds { + tot = tot.Add(decimal.NewFromBigInt(sched.Quantity, -18).Sub(decimal.NewFromBigInt(sched.VestedQuantity, -18))) + } + return tot, nil +} diff --git a/polycat/tankchef.go b/polycat/tankchef.go new file mode 100644 index 0000000..241c74e --- /dev/null +++ b/polycat/tankchef.go @@ -0,0 +1,41 @@ +package polycat + +import ( + "context" + "math/big" + + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polycat/contracts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type TankChefService struct { + client evm.Client + contract *contracts.TankChef +} + +func NewTankChefService(c evm.Client, address string) (*TankChefService, error) { + contract, err := contracts.NewTankChef(common.HexToAddress(address), c) + if err != nil { + return nil, errors.Wrap(err, "init contract") + } + return &TankChefService{ + contract: contract, + client: c, + }, nil +} + +func (s *TankChefService) Harvest(ctx context.Context, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.Withdraw(options.TransactOpts, big.NewInt(0)) + }, opts...) +} + +func (s *TankChefService) Deposit(ctx context.Context, amount decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return s.contract.Deposit(options.TransactOpts, amount.Shift(18).BigInt()) + }, opts...) +} diff --git a/polycat/tokens.go b/polycat/tokens.go new file mode 100644 index 0000000..3056044 --- /dev/null +++ b/polycat/tokens.go @@ -0,0 +1,30 @@ +package polycat + +import ( + "context" + + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polycat/contracts" + "git.lehouerou.net/laurent/evm/polygon" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" +) + +var ( + FISH = common.HexToAddress("0x3a3Df212b7AA91Aa0402B9035b098891d276572B") + OLDPAW = common.HexToAddress("0x6971aca589bbd367516d70c3d210e4906b090c96") + PAW = common.HexToAddress("0xbc5b59ea1b6f8da8258615ee38d40e999ec5d74f") + PAWFISHLP = common.HexToAddress("0xc7080deb5d75d528ba36eb3bec0b4c27797752fa") + WBTCWETHLP = common.HexToAddress("0xbbbd54c1cd649288d2e584917778eeccd8d8254d") +) + +func MigrateOldPawToV2(ctx context.Context, client *polygon.Client, opts ...evm.ExecutionOption) (evm.Transaction, error) { + pawv2, err := contracts.NewPawV2(PAW, client) + if err != nil { + return nil, errors.Wrap(err, "init pawv2 contract") + } + return client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return pawv2.Migrate(options.TransactOpts) + }, opts...) +} diff --git a/polygon/client.go b/polygon/client.go new file mode 100644 index 0000000..212ed13 --- /dev/null +++ b/polygon/client.go @@ -0,0 +1,30 @@ +package polygon + +import ( + "context" + + "git.lehouerou.net/laurent/evm" + "github.com/pkg/errors" +) + +const ( + RpcUrl = "https://polygon-rpc.com" +) + +type Client struct { + evm.Client +} + +func NewClientWithUrl(ctx context.Context, rpcurl string, privatekey string, options ...evm.ClientOption) (*Client, error) { + ethclient, err := evm.NewClient(ctx, rpcurl, privatekey, NewTokenMapper(), options...) + if err != nil { + return nil, errors.Wrap(err, "creating ethereum client") + } + return &Client{ + ethclient, + }, nil +} + +func NewClient(ctx context.Context, privatekey string, options ...evm.ClientOption) (*Client, error) { + return NewClientWithUrl(ctx, RpcUrl, privatekey, options...) +} diff --git a/polygon/tokenmapper.go b/polygon/tokenmapper.go new file mode 100644 index 0000000..736661f --- /dev/null +++ b/polygon/tokenmapper.go @@ -0,0 +1,254 @@ +package polygon + +import ( + "git.lehouerou.net/laurent/evm" + "github.com/ethereum/go-ethereum/common" +) + +var tokens = map[string]string{ + "$DG": "0x2a93172c8dccbfbc60a39d56183b7279a2f647b4", + "0xBTC": "0x71b821aa52a49f32eed535fca6eb5aa130085978", + "1INCH": "0x9c2c5fd7b07e95ee044ddeba0e97a665f142394f", + "AAVE": "0xd6df932a45c0f255f85145f286ea0b292b21c90b", + "ADDY": "0xc3fdbadc7c795ef1d6ba111e06ff8f16a20ea539", + "AGIX": "0x190eb8a183d22a4bdf278c6791b152228857c033", + "AIOZ": "0xe2341718c6c0cbfa8e6686102dd8fbf4047a9e9b", + "ALN": "0xa8fcee762642f156b5d757b6fabc36e06b6d4a1a", + "AMP": "0x0621d647cecbfb64b79e44302c1933cb4f27054d", + "ARMOR": "0x5de4005155933c0e1612ce808f12b4cd8daabc82", + "ATA": "0x0df0f72ee0e5c9b7ca761ecec42754992b2da5bf", + "BAC": "0xcde5e3d90631cacb842fa86f62dd0fc08a3ce43d", + "BAL": "0x9a71012b13ca4d3d0cdc72a177df3ef03b0e76a3", + "BAND": "0xa8b1e0764f85f53dfe21760e8afe5446d82606ac", + "BAT": "0x3cef98bb43d732e2f285ee605a8158cde967d219", + "BEPRO": "0x07cc1cc3628cc1615120df781ef9fc8ec2feae09", + "BIFI": "0xfbdd194376de19a88118e84e279b977f165d01b8", + "BLUE": "0xe7f960685aba7327ada3b161ea252703c87be0bf", + "BLZ": "0x438b28c5aa5f00a817b7def7ce2fb3d5d1970974", + "BNB": "0x3BA4c387f786bFEE076A58914F5Bd38d668B42c3", + "BNT": "0xc26d47d5c33ac71ac5cf9f776d63ba292a4f7842", + "BNTY": "0x0f40d69ff494a9e74b1f20a89eff299b2a05918f", + "BONE": "0x80244c2441779361f35803b8c711c6c8fc6054a3", + "BORING": "0xff88434e29d1e2333ad6baa08d358b436196da6b", + "BTC2x-FLI": "0x4b54bc363f5f9c6e0fcd82eac6919ae213464cc6", + "BTU": "0xfdc26cda2d2440d0e83cd1dee8e8be48405806dc", + "BUSD": "0xdab529f40e671a1d4bf91361c21bf9f0c9712ab7", + "BZRX": "0x54cfe73f2c7d0c4b62ab869b473f5512dc0944d2", + "CARD": "0x3a4bed49ab592a227bae8f41efd0d38e6e06d96c", + "CEL": "0xd85d1e945766fea5eda9103f918bd915fbca63e6", + "CHI": "0x0000000000004946c0e9f43f4dee607b0ef1fa1c", + "CHSB": "0x67ce67ec4fcd4aca0fcb738dd080b2a21ff69d75", + "CHZ": "0xf1938ce12400f9a761084e7a80d37e732a4da056", + "CNT": "0xd1e6354fb05bf72a8909266203dab80947dceccf", + "COMBO": "0x6ddb31002abc64e1479fc439692f7ea061e78165", + "COMP": "0x8505b9d2254a7ae468c0e9dd10ccea3a837aef5c", + "CRO": "0xada58df0f643d959c2a47c9d4d4c1a4defe3f11c", + "CRV": "0x172370d5cd63279efa6d502dab29171933a610af", + "CTI": "0x8ba941b64901e306667a287a370f145d98811096", + "CXO": "0xf2ae0038696774d65e67892c9d301c5f2cbbda58", + "DAI": "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063", + "DEC": "0x314338767151e6ed23db8a41c6f6943c1958ee56", + "DEFIT": "0x428360b02c1269bc1c79fbc399ad31d58c1e8fda", + "DEFT": "0xdef1fac7bf08f173d286bbbdcbeeade695129840", + "DERI": "0x3d1d2afd191b165d140e3e8329e634665ffb0e5e", + "DFYN": "0xc168e40227e4ebd8c1cae80f7a55a4f0e6d66c97", + "DHT": "0x8c92e38eca8210f4fcbf17f0951b198dd7668292", + "DOUGH": "0x990f860968714c2d16e91ec0cd9709a94264cf64", + "DOV": "0x0e0ffc562d72316b783e887bbaae1fd794adb530", + "DSLA": "0xa0e390e9cea0d0e8cd40048ced9fa9ea10d71639", + "EDR": "0x1ac417f1dd23504aac2076d854581f03196403fd", + "ELON": "0xe0339c80ffde91f3e20494df88d4206d86024cdf", + "EMON": "0xd6a5ab46ead26f49b03bbb1f9eb1ad5c1767974a", + "ENJ": "0x7ec26842f195c852fa843bb9f6d8b583a274a157", + "ETH2x-FLI": "0x66d7fdcc7403f18cae9b0e2e8385649d2acbc12a", + "EURS": "0xe111178a87a3bff0c8d18decba5798827539ae99", + "EWTB": "0x43e4b063f96c33f0433863a927f5bad34bb4b03d", + "FCL": "0x6f934b45fc6043527d73c7c99313dd838e723db7", + "FEG": "0xf391f574c63d9b8764b7a1f56d6383762e07b75b", + "FET": "0x7583feddbcefa813dc18259940f76a02710a8905", + "FISH": "0x3a3df212b7aa91aa0402b9035b098891d276572b", + "FOAM": "0x66e16d50c07a01bb473ec794349d45aa1a0e5dc2", + "FORTH": "0x5ecba59dacc1adc5bdea35f38a732823fc3de977", + "FOX": "0x65a05db8322701724c197af82c9cae41195b0aa8", + "FRAX": "0x45c32fa6df82ead1e2ef74d17b76547eddfaff89", + "FREE": "0x7cef6ed1e07079e174601d39066ad0856cb47988", + "FRONT": "0xa3ed22eee92a3872709823a6970069e12a4540eb", + "FSN": "0xfa1171334cb3a0f0a91e8ca6765f10e9638d1cbf", + "FTM": "0xc9c1c1c20b3658f8787cc2fd702267791f224ce1", + "FXS": "0x1a3acf6d19267e2d3e7f898f42803e90c9219062", + "GAJ": "0xf4b0903774532aee5ee567c02aab681a81539e92", + "GARD": "0xf89250e83fa2f33058385c98c7c44e723b040359", + "GBYTE": "0xab5f7a0e20b0d056aed4aa4528c78da45be7308b", + "GET": "0xdb725f82818de83e99f1dac22a9b5b51d3d04dd4", + "GFI": "0x874e178a2f3f3f9d34db862453cd756e7eab0381", + "GHST": "0x385eeac5cb85a38a9a07a70c73e0a3271cfb54a7", + "GLM": "0x0b220b82f3ea3b7f6d9a1d8ab58930c064a2b5bf", + "GMEE": "0xcf32822ff397ef82425153a9dcb726e5ff61dca7", + "GNO": "0x5ffd62d3c3ee2e81c00a7b9079fb248e7df024a8", + "GRT": "0x5fe2b58c013d7601147dcdd68c143a77499f5531", + "GRUMPY": "0x733726968ae55dc58c26dbdc193fea256a704ba4", + "GTC": "0xdb95f9188479575f3f718a245eca1b3bf74567ec", + "GUSD": "0xc8a94a3d3d2dabc3c1caffffdca6a7543c3e3e65", + "HEX": "0x23d29d30e35c5e8d321e1dc9a8a61bfd846d4c5c", + "HONOR": "0xb82a20b4522680951f11c94c54b8800c1c237693", + "HOPR": "0x6ccbf3627b2c83afef05bf2f035e7f7b210fe30d", + "HOT": "0x0c51f415cf478f8d08c246a6c6ee180c5dc3a012", + "HT": "0xfad65eb62a97ff5ed91b23afd039956aaca6e93b", + "HUSD": "0x2088c47fc0c78356c622f79dba4cbe1ccfa84a91", + "ICE": "0x4a81f8796e0c6ad4877a51c86693b0de8093f2ef", + "IMX": "0x60bb3d364b765c497c8ce50ae0ae3f0882c5bd05", + "INJ": "0x4e8dc2149eac3f3def36b1c281ea466338249371", + "INSUR": "0x8a0e8b4b0903929f47C3ea30973940D4a9702067", + "INXT": "0xe64106154816a252da7728e35a0060f15d66cb34", + "IOTX": "0xf6372cdb9c1d3674e83842e3800f2a62ac9f3c66", + "IQ": "0xb9638272ad6998708de56bbc0a290a1de534a578", + "IRON": "0xd86b5923f3ad7b585ed81b448170ae026c65ae9a", + "JRT": "0x596ebe76e2db4470966ea395b0d063ac6197a8c5", + "KEEP": "0x42f37a1296b2981f7c3caced84c5096b2eb0c72c", + "KNC": "0x1c954e8fe737f99f68fa1ccda3e51ebdb291948c", + "Krill": "0x05089c9ebffa4f0aca269e32056b1b36b37ed71b", + "LCX": "0xe8a51d0dd1b4525189dda2187f90ddf0932b5482", + "LEND": "0x313d009888329c9d1cf4f75ca3f32566335bd604", + "LEO": "0x06d02e9d62a13fc76bb229373fb3bbbd1101d2fc", + "LINK": "0x53e0bca35ec356bd5dddfebbd1fc0fd03fabad39", + "LIT": "0xe6e320b7bb22018d6ca1f4d8cea1365ef5d25ced", + "LPOOL": "0x9e7deba360c77949bb75d16dc81b2393c15005eb", + "LPT": "0x3962f4a0a0051dcce0be73a7e09cef5756736712", + "LRC": "0x84e1670f61347cdaed56dcc736fb990fbb47ddc1", + "MANA": "0xa1c57f48f0deb89f569dfbe6e2b7f46d33606fd4", + "MASK": "0x2b9e7ccdf0f4e5b24757c1e1a80e311e34cb10c7", + "MFT": "0x91ca694d2b293f70fe722fba7d8a5259188959c3", + "MKR": "0x6f7C932e7684666C9fd1d44527765433e01fF61d", + "MOON": "0xc56d17dd519e5eb43a19c9759b5d5372115220bd", + "MOVE": "0x521cddc0cba84f14c69c1e99249f781aa73ee0bc", + "MTA": "0xf501dd45a1198c2e1b5aef5314a68b9006d842e0", + "MTCL": "0x3642c3c8ebe0b36a29e37809e1c9a7de06bc0b26", + "NEXO": "0x41b3966b4ff7b427969ddf5da3627d6aeae9a48e", + "NPX": "0x106035dedca635d75d6ff05f98f25916829edb77", + "OCC": "0xf30355ba14b2d3b31597ec71a4542f57e902cb80", + "OCEAN": "0x282d8efce846a88b159800bd4130ad77443fa1a1", + "OGN": "0xa63beffd33ab3a2efd92a39a7d2361cee14ceba8", + "OIL": "0x65DfA90171e1bd9060209405026C4E1f4A8E58df", + "OM": "0xc3ec80343d2bae2f8e680fdadde7c17e71e114ea", + "OMEN": "0x76e63a3E7Ba1e2E61D3DA86a87479f983dE89a7E", + "OMG": "0x62414d03084eeb269e18c970a21f45d2967f0170", + "ONG": "0xb6f10be9201fb110b3aa275267a234e84ade8e95", + "OPENSTORE": "0x2953399124f0cbb46d2cbacd8a89cf0599974963", + "ORAI": "0xf4310adb83694bc4808e0c5ca8f7027c6127921d", + "ORBS": "0x614389eaae0a6821dc49062d56bda3d9d45fa2ff", + "OVR": "0x1631244689ec1fecbdd22fb5916e920dfc9b8d30", + "OXT": "0x9880e3dda13c8e7d4804691a45160102d31f6060", + "PAID": "0xeAEf6cAf6d5894EDB2D4EA7ec11eC4AB655f1cBF", + "PAINT": "0x7c28f627ea3aec8b882b51eb1935f66e5b875714", + "PAR": "0x7b367a058f370c0057762280547d0b974cf3ac10", + "PAX": "0x6f3b3286fd86d8b47ec737ceb3d0d354cc657b3e", + "PAXG": "0x553d3d295e0f695b9228246232edf400ed3560b5", + "PLU": "0x7dc0cb65ec6019330a6841e9c274f2ee57a6ca6c", + "PNK": "0xad93e067e149f0a5ecd12d8ea83b05581dd6374c", + "PNODE": "0x4e92f6f10496f3fcb790cc6969cc15b87c8f9199", + "POLI": "0x6fb54ffe60386ac33b722be13d2549dd87bf63af", + "POLY": "0xcb059c5573646047d6d88dddb87b745c18161d3b", + "POND": "0x73580a2416a57f1c4b6391dba688a9e4f7dbece0", + "POOL": "0x25788a1a171ec66da6502f9975a15b609ff54cf6", + "POWR": "0x0aab8dc887d34f00d50e19aee48371a941390d14", + "PPDEX": "0x127984b5e6d5c59f81dacc9f1c8b3bdc8494572e", + "PRQ": "0x9377eeb7419486fd4d485671d50baa4bf77c2222", + "PUP": "0xcfe2cf35d2bdde84967e67d00ad74237e234ce59", + "PUSD": "0x9af3b7dc29d3c4b1a5731408b6a9656fa7ac3b72", + "PYQ": "0x5a3064cbdccf428ae907796cf6ad5a664cd7f3d8", + "PolyDoge": "0x8a953cfe442c5e8855cc6c61b1293fa648bae472", + "QI": "0x580a84c73811e1839f75d86d75d88cca0c241ff4", + "QUICK": "0x831753dd7087cac61ab5644b308642cc1c33dc13", + "RARI": "0x780053837ce2ceead2a90d9151aa21fc89ed49c2", + "RCN": "0x89c296be2f904f3e99a6125815b4b78f5388d2dd", + "RLC": "0xbe662058e00849c3eef2ac9664f37fefdf2cdbfe", + "RNDR": "0x61299774020da444af134c82fa83e3810b309991", + "ROLL": "0xc68e83a305b0fad69e264a1769a0a070f190d2d6", + "ROUTE": "0x16eccfdbb4ee1a85a33f3a9b21175cd7ae753db4", + "RPL": "0x7205705771547cf79201111b4bd8aaf29467b9ec", + "SAND": "0xc6d54d2f624bc83815b49d9c2203b1330b841ca0", + "SDO": "0x66c59dded4ef01a3412a8b019b6e41d4a8c49a35", + "SDS": "0xab72ee159ff70b64beecbbb0fbbe58b372391c54", + "SENT": "0x48e3883233461c2ef4cb3fcf419d6db07fb86cea", + "SNX": "0x50b728d8d964fd00c2d0aad81718b71311fef68a", + "SPI": "0x068180071617528606371c31892ecbf2b70ac1d2", + "SPN": "0xeab9cfb094db203e6035c2e7268a86debed5bd14", + "SRAT": "0x1132f58810ee9ff13e97aeccd8dda688cc5eb8f4", + "SRM": "0x6bf2eb299e51fc5df30dec81d9445dde70e3f185", + "STACK": "0xccbe9b810d6574701d324fd6dbe0a1b68f9d5bf7", + "STAKE": "0xeb5c9e515629b725d3588a55e2a43964dcfde8ca", + "STC": "0x779b299ea455d35a44fe9bac48648be22c08dea2", + "STND": "0x08be454de533509e8832b257116c5506e55b0b64", + "SUSHI": "0x0b3f868e0be5597d5db7feb59e1cadbb0fdda50a", + "SWISE": "0xbbbe128568222623d21299f019a978c8587b33dc", + "SXP": "0x6abb753c1893194de4a83c6e8b4eadfc105fd5f5", + "TAP": "0x10635bf5c17f5e4c0ed9012aef7c12f96a57a4dd", + "TEL": "0xdf7837de1f2fa4631d716cf2502f8b230f1dcc32", + "THETA": "0xb46e0ae620efd98516f49bb00263317096c114b2", + "TIDAL": "0xB41EC2c036f8a42DA384DDE6ADA79884F8b84b26", + "TITAN": "0xaaa5b9e6c589642f98a1cda99b9d024b8407285a", + "TORG": "0xe9993763e0b7f7d915a62a5f22a6e151f91d98a8", + "TORN": "0x23fe1ee2f536427b7e8ac02fb037a7f867037fe8", + "TRB": "0xe3322702bedaaed36cddab233360b939775ae5f1", + "TUSD": "0x2e1ad108ff1d8c782fcbbb89aad783ac49586756", + "UBT": "0x7fbc10850cae055b27039af31bd258430e714c62", + "UMA": "0x3066818837c5e6ed6601bd5a91b0762877a6b731", + "UMX": "0x5df1a47e05b4caba0ed3df13662642f05314764d", + "UNI": "0xb33eaad8d922b1083446dc23f610c2567fb5180f", + "USDC": "0x2791bca1f2de4661ed88a30c99a7a9449aa84174", + "USDK": "0xd07a7fac2857901e4bec0d89bbdae764723aab86", + "USDT": "0xc2132d05d31c914a87c6611c10748aeb04b58e8f", + "UST": "0x692597b009d13c4049a947cab2239b7d6517875f", + "VEE": "0xf1c1a3c2481a3a8a3f173a9ab5ade275292a6fa3", + "VGX": "0x054c42b6414747f5263b4a86f21b1afad00326bf", + "VSP": "0x09c5a4bca808bd1ba2b8e6b3aaf7442046b4ca5b", + "WBTC": "0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6", + "WEXpoly": "0x4c4bf319237d98a30a929a96112effa8da3510eb", + "WFIL": "0xede1b77c0ccc45bfa949636757cd2ca7ef30137f", + "WMATIC": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270", + "WOLF": "0x8f18dc399594b451eda8c5da02d0563c0b2d0f16", + "WOO": "0x1b815d120b3ef02039ee11dc2d33de7aa4a8c603", + "WOOFY": "0xfce22ad802bbc9fe74534575b166d06198bd66ea", + "WPR": "0xcbab27b2d5b468eea509bd430100922341bc3f1a", + "WSPP": "0x46d502fac9aea7c5bc7b13c8ec9d02378c33d36f", + "XED": "0x2fe8733dcb25bfbba79292294347415417510067", + "XIV": "0xde799636af0d8d65a17aaa83b66cbbe9b185eb01", + "XTK": "0x22308317a4aa9e8196065e0b3647e582d44c4d7b", + "XYO": "0xd2507e7b5794179380673870d88b22f94da6abe0", + "YELD": "0xd0f3121a190d85de0ab6131f2bcecdbfcfb38891", + "YFI": "0xda537104d6a5edd53c6fbba9a898708e465260b6", + "YOP": "0x103308793661879166464cd0d0370ac3b8a2a1cb", + "ZRX": "0x5559edb74751a0ede9dea4dc23aee72cca6be3d5", + "aETHc": "0xc4e82ba0fe6763cbe5e9cbca0ba7cbd6f91c6018", + "amAAVE": "0x1d2a0e5ec8e5bbdca5cb219e649b565d8e5c3360", + "amDAI": "0x27f8d03b3a2196956ed754badc28d73be8830a6e", + "amUSDC": "0x1a13f4ca1d028320a707d99520abfefca3998b7f", + "amUSDT": "0x60d55f02a771d515e077c9c2403a1ef324885cec", + "amWBTC": "0x5c2ed810328349100a66b82b78a1791b101c9d61", + "amWETH": "0x28424507fefb6f7f8e9d3860f56504e4e5f5f390", + "amWMATIC": "0x8df3aad3a84da6b69a4da8aec3ea40d9091b2ac4", + "dQUICK": "0xf28164a485b0b2c90639e47b0f377b4a438a16b1", + "eRSDL": "0x5095cc6511b70e287bc525aa57afbc60eb73ac47", + "iFUND": "0x4ba47b10ea8f544f8969ba61df3e5be67692a122", + "jCHF": "0xbD1463F02f61676d53fd183C2B19282BFF93D099", + "jEUR": "0x4e3decbb3645551b8a19f0ea1678079fcb33fb4c", + "jGBP": "0x767058F11800FBA6A682E73A6e79ec5eB74Fac8c", + "maUSDC": "0x9719d867a500ef117cc201206b8ab51e794d3f82", + "miMATIC": "0xa3fa99a148fa48d14ed51d610c367c61876997f1", + "pBTC": "0xd7ecf95cf7ef5256990beaf4ac895cd9e64cb947", + "pWINGS": "0x845e76a8691423fbc4ecb8dd77556cb61c09ee25", + "polyBUNNY": "0x4c16f69302ccb511c5fac682c7626b9ef0dc126a", + "renBTC": "0xdbf31df14b66535af65aac99c32e9ea844e14501", + "renDOGE": "0xce829a89d4a55a63418bcc43f00145adef0edb8e", + "renFIL": "0xc4ace9278e7e01755b670c0838c3106367639962", + "sUSD": "0xf81b4bec6ca8f9fe7be01ca734f55b2b6e03a7a0", + "wCELO": "0xc30dd0cce2e683aa68c87c280e73beb3dec9b3ba", +} + +func NewTokenMapper() evm.TokenMapper { + tm := evm.NewTokenMapper() + for s, s2 := range tokens { + tm.AddToken(s, common.HexToAddress(s2)) + } + return tm +} diff --git a/polygon/wmatic.go b/polygon/wmatic.go new file mode 100644 index 0000000..6d80d1b --- /dev/null +++ b/polygon/wmatic.go @@ -0,0 +1,44 @@ +package polygon + +import ( + "context" + + "git.lehouerou.net/laurent/evm" + "git.lehouerou.net/laurent/evm/polygon/contracts" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type WMATIC struct { + evm.Token + client evm.Client + contract *contracts.Wmatic +} + +func NewWrappedMaticService(client evm.Client) (*WMATIC, error) { + address, err := client.TokenService().TokenAddressBySymbol("WMATIC") + if err != nil { + return nil, errors.Wrap(err, "failed to get wmatic address") + } + t, err := evm.NewToken(client, address) + if err != nil { + return nil, errors.Wrap(err, "init token contract") + } + c, err := contracts.NewWmatic(address, client) + if err != nil { + return nil, errors.Wrap(err, "init wmatic contract") + } + return &WMATIC{ + Token: t, + client: client, + contract: c, + }, nil +} + +func (w *WMATIC) Unwrap(ctx context.Context, amount decimal.Decimal, opts ...evm.ExecutionOption) (evm.Transaction, error) { + return w.client.Execute(ctx, + func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) { + return w.contract.Withdraw(options.TransactOpts, w.ValueToBigInt(amount)) + }, opts...) +} diff --git a/token.go b/token.go index b6dfef7..0188f1a 100644 --- a/token.go +++ b/token.go @@ -13,6 +13,8 @@ import ( ) type Token interface { + Client() Client + Address() common.Address Name() string Symbol() string @@ -65,6 +67,10 @@ func NewToken(client Client, address common.Address) (Token, error) { }, nil } +func (t *baseToken) Client() Client { + return t.client +} + func (t *baseToken) TotalSupply() (decimal.Decimal, error) { s, err := t.contract.TotalSupply(&bind.CallOpts{}) if err != nil {