diff --git a/cmd/promotees/main.go b/cmd/promotees/main.go new file mode 100644 index 0000000..7253085 --- /dev/null +++ b/cmd/promotees/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + + libapp "github.com/KyberNetwork/tradelogs/internal/app" + "github.com/KyberNetwork/tradelogs/internal/dbutil" + "github.com/KyberNetwork/tradelogs/internal/promotionworker" + "github.com/KyberNetwork/tradelogs/pkg/evmlistenerclient" + + server "github.com/KyberNetwork/tradelogs/internal/server/promotees" + "github.com/KyberNetwork/tradelogs/pkg/promotionparser" + "github.com/KyberNetwork/tradelogs/pkg/promotionparser/oneinchv2" + "github.com/KyberNetwork/tradelogs/pkg/promotionstorage" + "github.com/go-redis/redis/v8" + "github.com/jmoiron/sqlx" + "github.com/urfave/cli" + "go.uber.org/zap" +) + +func main() { + app := libapp.NewApp() + app.Name = "Promotees fetcher service" + app.Action = run + app.Flags = append(app.Flags, libapp.PostgresSQLFlags("tradelogs")...) + app.Flags = append(app.Flags, libapp.RedisFlags()...) + app.Flags = append(app.Flags, libapp.EvmListenerFlags()...) + app.Flags = append(app.Flags, libapp.HTTPServerFlags()...) + + if err := app.Run(os.Args); err != nil { + log.Panic(err) + } +} + +func run(c *cli.Context) error { + logger, _, flush, err := libapp.NewLogger(c) + if err != nil { + return fmt.Errorf("new logger: %w", err) + } + + defer flush() + + zap.ReplaceGlobals(logger) + l := logger.Sugar() + l.Infow("app starting ..") + + db, err := initDB(c) + if err != nil { + l.Panicw("cannot init DB", "err", err) + } + redis, err := initRedis(c) + if err != nil { + l.Panicw("cannot init redis", "err", err) + } + s := promotionstorage.New(l, db) + listener := evmlistenerclient.New(l, libapp.EvmlistenerConfigFromCli(c), redis) + err = listener.Init(context.Background()) + if err != nil { + l.Errorw("Error while init listener service") + return err + } + + parsers := []promotionparser.Parser{oneinchv2.MustNewParser()} + + w := promotionworker.New(l, s, listener, parsers) + + apiServer := server.New(s, c.String(libapp.HTTPPromoteeServerFlag.Name)) + go func() { + if err := apiServer.Run(); err != nil { + panic(err) + } + }() + + return w.Run(context.Background()) +} + +func initDB(c *cli.Context) (*sqlx.DB, error) { + db, err := libapp.NewDB(map[string]interface{}{ + "host": c.String(libapp.PostgresHost.Name), + "port": c.Int(libapp.PostgresPort.Name), + "user": c.String(libapp.PostgresUser.Name), + "password": c.String(libapp.PostgresPassword.Name), + "dbname": c.String(libapp.PostgresDatabase.Name), + "sslmode": "disable", + }) + if err != nil { + return nil, err + } + + _, err = dbutil.RunMigrationUp(db.DB, c.String(libapp.PostgresMigrationPath.Name), + c.String(libapp.PostgresDatabase.Name)) + if err != nil { + return nil, err + } + return db, nil +} + +func initRedis(c *cli.Context) (redis.UniversalClient, error) { + redis := redis.NewUniversalClient(libapp.RedisOptionFromFlags(c)) + if _, err := redis.Ping(context.Background()).Result(); err != nil { + return nil, err + } + return redis, nil +} diff --git a/cmd/tradelogs/migrations/000014_init_promotee_.up.sql b/cmd/tradelogs/migrations/000014_init_promotee_.up.sql new file mode 100644 index 0000000..92bac40 --- /dev/null +++ b/cmd/tradelogs/migrations/000014_init_promotee_.up.sql @@ -0,0 +1,152 @@ +CREATE TABLE IF NOT EXISTS promoteesName ( + promoter TEXT NOT NULL, + name TEXT NOT NULL, + PRIMARY KEY(promoter) +); + +CREATE TABLE IF NOT EXISTS promotees ( + promoter TEXT NOT NULL, + promotee TEXT NOT NULL, + timestamp BIGINT, + event_hash TEXT, + chain_id TEXT NOT NULL, + block_number BIGINT, + PRIMARY KEY(promoter, promotee, chain_id) +); + +CREATE INDEX block_number_idx ON promotees (block_number); + +INSERT INTO promotees (promoter, promotee, timestamp, event_hash, chain_id, block_number) VALUES +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0x1e9d349cec77fea6481f009593101d0e20a69490',1690672115, '0xf8cf20ddcd5eaf81ea4967c60402d1f3805804126fd4371bf9e39a7605ccad02', '1', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x09804914f1e3f18e234540f6ecec1386d8ef4d9f',1695356375, '0xa74b54b6c147ad9a91fa9921b7f293bd8ba0b56c14122cb2b2096bc2b7a16723', '137', 18200000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0xd1742b3c4fbb096990c8950fa635aec75b30781a',1690751243, '0x4dc9aa484e1afe6f9e01280925504841c26a81e0db09c6406ca7b1869bdc6ea8', '1', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xf030335f3f82e12bf4bd3c3e2e431a6e18952c3a',1695356375, '0xa74b54b6c147ad9a91fa9921b7f293bd8ba0b56c14122cb2b2096bc2b7a16723', '100', 18200000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x20ac2321dea89ad8b2dfe2245e837c25713a0852',1695356375, '0xa74b54b6c147ad9a91fa9921b7f293bd8ba0b56c14122cb2b2096bc2b7a16723', '250', 18200000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '137', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x0b8a49d816cc709b6eadb09498030ae3416b66dc',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '1', 17800000), +('0xdcdf16a03360d4971ca4c1fd9967a47125f3c995', '0x8571c129f335832f6bbc76d49414ad2b8371a422',1695270539, '0xcdd51783d7d2d51cf63e046607261d4a26890696669a516ced81975b9da03d47', '1', 18200000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x9d4eb7189cd57693c3d01f35168715e1e589cea8',1695356375, '0xa74b54b6c147ad9a91fa9921b7f293bd8ba0b56c14122cb2b2096bc2b7a16723', '42161', 18200000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x70b0a8a99e4136c3cd3859240b47c8effe49417a',1690409171, '0x97d237aefc4ef566d7f924f263092e9d46a5eb6d43e17ffbb62141e95ee8e205', '137', 17800000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac',1690409135, '0xc7fe17e2a164861ac231efe643b2449ff3895837951665e10f1f3beeb5f8b773', '42161', 17800000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x70b0a8a99e4136c3cd3859240b47c8effe49417a',1690409099, '0xae078776be993a3ff0abe0bd33a2d4e2be7723f798d8e9cdc95a0bf5e5a4a0cf', '250', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xe16e2f35da363a4bd330812e7cffb3f51a97c7d1',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '42161', 17800000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc6c7565644ea1893ad29182f7b6961aab7edfed0',1690672127, '0xa5b227ccf655fa1c5d2062ce7c014cf42a75ba38bb01c9c8b98d9e00ed9ab449', '56', 17800000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac',1690408799, '0x871bf17feb6189c3f6dc786bbe776a77a2d95d7cfe0c80d41afffcd77d219e8b', '100', 17800000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac',1690407875, '0x6bd90f313fbf35d017adcce8294d33023c0e664d9b526816174ca8ade9cf8544', '1', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x7ff86f6ca68a95241f860bc98e42f758b22e9f1a',1695356375, '0xa74b54b6c147ad9a91fa9921b7f293bd8ba0b56c14122cb2b2096bc2b7a16723', '43114', 18200000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc6c7565644ea1893ad29182f7b6961aab7edfed0',1690672163, '0x83d4a9c44922fb261f9b7bebf447ab70ad2c4b8eea0fcf4c40aff77cfd9753f6', '43114', 17800000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x70b0a8a99e4136c3cd3859240b47c8effe49417a',1690409075, '0x209e0d87d179856ce0d59786c495b9988aeb5d6b89abfd6a6193cff95dcc8a62', '10', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '250', 17800000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc6c7565644ea1893ad29182f7b6961aab7edfed0',1690672151, '0xc86333952893fb0879cb2db03f25f8e4b2641620909a623a3c179d5b8440fb8e', '42161', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xf38fbc3f7484a28f8d6150b0f296b9d68c8bd9e0',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '43114', 17800000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac',1690408871, '0xb52f5d46764ca9f0431d2fa9a8d4d4483661662c3cba45d58cd02d7d3fea00f3', '43114', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x96805b915a4fc2f5cb8c2324dfe7924cb4f3257d',1695281531, '0xf56d063851b5e339187c2697c8cf7d7474c0cc7d13825c7cac5ae2e3cdcd6134', '56', 18200000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x377a1286ff83df266ff11bede2ef600044f3626b',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '56', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '42161', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '56', 17800000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc6c7565644ea1893ad29182f7b6961aab7edfed0',1690672175, '0xc4524d84a37aa2b0bccfabad9986ff89a826e3e13de255c55c88bad444ee2e95', '10', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '100', 17800000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0xa9ff271ee217dc1c9ce3f7ebf0d6f096842cd82f',1690997831, '0xf1ab60e0f5c5310de2472c1002d4887d4089130c0ac558afd8436198942b0347', '42161', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '10', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x377a1286ff83df266ff11bede2ef600044f3626b',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '250', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xd71e77361b166ab91d867fdfa8b9fc9c8f53cd21',1695099635, '0xee48010381faf2790b4b406fbdc3d39f649580cc99c2bc43e8458ed23d966499', '10', 18200000), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', '0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac',1690408823, '0xd376bf9564d91dd56953331d69077be9e7425fa9c999d5a6d171b4f466e2ae9e', '56', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xc3c8a64f2fadd0a836007ef4fe3a76d62dd6759a',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '100', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '43114', 17800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xf38fbc3f7484a28f8d6150b0f296b9d68c8bd9e0',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '10', 17800000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0xd1742b3c4fbb096990c8950fa635aec75b30781a',1690751243, '0x4dc9aa484e1afe6f9e01280925504841c26a81e0db09c6406ca7b1869bdc6ea8', '42161', 17800000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0x01372be9616ff00469d3e509b77d6960af757180',1691459783, '0x46ab12e2cb6e5e7c2a1e0a1da7735785b713124aeb93ba3093e64ed69451e624', '1', 17900000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xf1b2e1fef70e0383ef29618d02d0dd503ae239ae',1690537439, '0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b', '137', 17800000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc6c7565644ea1893ad29182f7b6961aab7edfed0',1690672139, '0x72ca88a6c85e0b5f11dd912a3dea116a0a784246a2c822db19c09e829adf0daf', '137', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1690946915, '0x3d60f68df749eb9a34b427955459d3f441c5051c6a2c202be64f696fbde1eec6', '1', 17800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0xad3b67bca8935cb510c8d18bd45f0b94f54a968f',1700711075, '0x612b3565e7d47cc48072c0b879c8dd3d0eeed4e0e775ae90522faca6178ca53a', '8453', 18600000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0x7f50d2d669cc5c554f71a9534f80ddcb511e5496',1702847159, '0xe9e1fd8ada7705649f1688c586d6938f8e7c8d18ba2d41d8ca8b1fd012163d37', '1', 18800000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0x874d26f8f5dd55ee1a4167c49965b991c1c9530a',1703192687, '0xd776b4a05a30c962e66c5944edd768ee8ef8d16ad8583e4e849d6fdf4c3b3442', '1', 18800000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0xd14699b6b02e900a5c2338700d5181a674fdb9a2',1703842967, '0x980b83c3bd879bda6ad3aed7058f0120cb6299ff2edc7701b0891d5718139b0d', '137', 18900000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0xd14699b6b02e900a5c2338700d5181a674fdb9a2',1704191423, '0x1748b1540185f8bf87068a1f71c569a079f94e38132e19111b4c1f75a0e0c62f', '1', 18900000), +('0x05d18b713dab812c34edb48c76cd9c836d56752b', '0xf14f17989790a2116fc0a59ca88d5813e693528f',1706599415, '0x3227851c46fe4f13c083319cae80c740a0ad187c0c29e002df31603cc7f4dadd', '1', 19100000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x9e9c9666b298155a315ec555044c1234a528cdd0',1709613863, '0xefd3fad3dcd5dd6ceb352e1053c8977d5d65c21e301574ae59026770bd2251f5', '8453', 19400000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x292cfcb8e1455ac95b45b35bcccd7e09a840fefc',1711544147, '0x4c12d3caf4c2066eab9d7d6aef940de77d34149060b2ba3d9dae6dbe2112fa61', '8453', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x90296538701c73af76758f4778916daa2407956f',1711610171, '0x54c03fdd964ccf4a81e66c62796c5c4d2cadbebc5401b216afb09397b354fa00', '8453', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x292cfcb8e1455ac95b45b35bcccd7e09a840fefc',1711628579, '0xe87fba4881bca052bef598df9f7d0dc83d631c797aa68d9e103af98342f2c328', '250', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0xbd628309c01d0c868a33155e3fa0f56bb0e768b3',1711799375, '0x97820f27f611ae3574d8c88c290ffc060cc88ec6bfb5e75b6ecfd4f4a3d9abce', '8453', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x6dbb8e47f8b56dbd8f94110195a503e24d1b9d87',1711807271, '0xf608289b9dd33517c260878b871efce7846685cce39d03bc10c5fd05442190df', '100', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x6dbb8e47f8b56dbd8f94110195a503e24d1b9d87',1711807271, '0xf608289b9dd33517c260878b871efce7846685cce39d03bc10c5fd05442190df', '43114', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x6dbb8e47f8b56dbd8f94110195a503e24d1b9d87',1711807271, '0xf608289b9dd33517c260878b871efce7846685cce39d03bc10c5fd05442190df', '56', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x0eab5f6c89322428da8f67a83e0a6adffa3d372e',1711807271, '0xf608289b9dd33517c260878b871efce7846685cce39d03bc10c5fd05442190df', '137', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x6dbb8e47f8b56dbd8f94110195a503e24d1b9d87',1711807271, '0xf608289b9dd33517c260878b871efce7846685cce39d03bc10c5fd05442190df', '10', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x6dbb8e47f8b56dbd8f94110195a503e24d1b9d87',1711807271, '0xf608289b9dd33517c260878b871efce7846685cce39d03bc10c5fd05442190df', '250', 19500000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x292cfcb8e1455ac95b45b35bcccd7e09a840fefc',1712131139, '0x07479227179956722fbe71a461b376b92375e9a784ab197ac76d0820059bf093', '42161', 19600000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xb86f32b648f4a17fc7c67bf29735c20c566e5a0c',1712194871, '0x4cf0e83a2f0d57943e0f6049d7936b5cb053d073ac464020e9f92a0c7ca633ba', '1', 19600000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x62f861201db5fdc04c48c976bf098c4dba0a061d',1714560767, '0xe12b5edd50d07569daf0c54fdb617fd7e3b965d979cfb2ea43c38cf5b308e749', '137', 19800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x429d51d948c75b8d029a150744f5914a1573eab4',1714975439, '0xe14c8e7397ee9c181c472de82a7fd55bf873860359ea716d5889a1b0f32456c2', '42161', 19800000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0x08278e7d05589bc52417c0340c12dcd0e54b200a',1715126975, '0x3a7dc8db9ee9aa45591e059a1400015a6f60292e2005147142cc6deefa2c94c2', '1', 19800000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0x12b26280e05f82510910ce31a0c03f0c37c6d3a9',1715243651, '0x77a260e1f0a190ed81e8c64f261113910d79b3fda80823194fece93aafbdbaee', '100', 19800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xf1ceb16d94083606db7f4d98400554f17125483b',1715308883, '0x2f866585d7a06c43190c95510359ba1a3eb3429d50730e524b4ae7f6324c13df', '8453', 19800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x6fb828b87c2ae4f0d857e6807989d352e133c050',1715311427, '0x2800184cf042e89eda4204475877fe2d5fa8e267ed019939c3d84063dd36adc1', '43114', 19800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x4bb133c4d1ab425874182de72cc3447485d7ae5f',1715312687, '0xbc1c1a59540dec747fad4bed80153f33d38461920f69cae0aa7a3162364c8f2e', '10', 19800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x46fd018b32a9315ef5b4c0866635457d36ab318d',1715314067, '0x172d9cc504c573330ba9819f5ef8ccae0823114b1a191de991d8a17f7be33642', '137', 19800000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0xee0559bd8f5e42bfb1d0e061ccc75a6cead965a8',1715318831, '0x86f33e059031e3cace2914895bdbfef91d7178ae8092741e0e6733fe48a6a037', '100', 19800000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0xdb650c9a90966cab9cd4299aad897099c9fc85ce',1715334815, '0x409a474e7612771a777fcb664b95ab7b9450b64071ea9ad182fa5edabb4bb940', '1', 19800000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0x98f8798cd6bff22c27018a5d7ce489dd8fbdc279',1715389487, '0xfe2a69aa378400bcdcdce736199f22a0dd69f68fff149fc9ecda3157db1c04be', '1', 19800000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0xd42b0ecf8a9f8ba9db7b0c989d73cf0bd5f83b66',1715404835, '0xee9f94f15da251c1ca35ef6c1e1b4e36e070d466d91312e876c07be69c9d678c', '0xd5e74de4385ef0eb1bb4db05a6a504f04d92e79d', 19800000), +('0xdcdf16a03360d4971ca4c1fd9967a47125f3c995', '0xa8c1c98aaf99a5dfc907d61b892b2ad624901185',1715588963, '0xef2c657738350ec21aa5980411976dae60728735f187469e3fa4acc1c1c345e2', '1', 19900000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0x74b882520b6b41296431a2d0eeca39b94127c45c',1715654603, '0x2cb28ad7f3dc91c6c519d04722353d02d50b67d31a9fe713bc6c03ab1e644ffa', '42161', 19900000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0x819d2b7f96f4e8d8f83788d42d0f8eb58a912c23',1715660699, '0x8d720ae71b75622afd1e9db3bc9b80fa8f5fb6a69bd54acf5a35f0ed170de71d', '42161', 19900000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0x664241f2d7dd1c33090080af6840355608efd9a9',1715668523, '0x8dbbb350fb15f26c7b20edd8b56a01cb4f1a986c05756c2c7bfe35ab49729df6', '1', 19900000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0xe6e2aeaa85210871286e901f8f650d76dcc657d1',1715719811, '0xd776dc3be94f7375b1d8c8f47837522f90d90eca0ef7edd6f7298d33967e4d8d', '1', 19900000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xd5e74de4385ef0eb1bb4db05a6a504f04d92e79d',1715760539, '0xd413c8500623393a068d536245221115dc8b0c648d91cb5c12c5a9c0454e7626', '1', 19900000), +('0x05d18b713dab812c34edb48c76cd9c836d56752b', '0x77ea4f236c644ffb5f97d0847e80c0b823a65ce7',1715849327, '0xe9ed8f1a6c8124a621de91d13661393f976e498ed2c7bce6e0664fa8155175c4', '1', 19900000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0x4427dc4d6723374b3b40e3a1865515044b1e9869',1716092303, '0x0ff15e235742c2aad3368ecb3bb536077965eccf42c674e466ad5acbc5398972', '1', 19900000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc1b19a08c2798c6930b8f3a44b7b0d08f4e198b8',1716888611, '0x1694fdf61ab8392db3175cce5358eab863ffe0f4be0ae88a549a6983c29174d1', '56', 20000000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc1b19a08c2798c6930b8f3a44b7b0d08f4e198b8',1716888743, '0x7e53c9e84375644acab763e0e53da38515fa7ee1a2644330318c3a15b05ad14c', '137', 20000000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc1b19a08c2798c6930b8f3a44b7b0d08f4e198b8',1716888779, '0xe451697d5581d8f5b6de735e8ec47674c51d96be5c5ef58398d88dbac3c4d1d0', '43114', 20000000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc1b19a08c2798c6930b8f3a44b7b0d08f4e198b8',1716888767, '0x9eee482ef9758d1a4cfb3aae797cf9d68d580ce84a9e818f41f97f3043eed3fb', '42161', 20000000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0x76c20c628a025bcbc2fc62e5cb8ecfbac5932086',1717061771, '0x145d8bf969cbb0c2f5f0c4edebeb7c620d1543a34c98103e191afc19a5b57d1e', '8453', 20000000), +('0xf63392356a985ead50b767a3e97a253ff870e91a', '0x98ae961b2b1ad8ce4a0cd3f773eb46d35453bca2',1717386239, '0xd8666b7f1627c0d1c6e2a4a90f455039bde20e262e8ed3bf070c6a640f955631', '324', 20000000), +('0xd3eeebc3f13532fa4bccab0275da36a413ad101b', '0xb02f39e382c90160eb816de5e0e428ac771d77b5',1718085035, '0x90fde9c393dec15784f9addc35a93bfa9f237bfc6f201ad4a98d64959ed919d0', '1', 20100000), +('0x05d18b713dab812c34edb48c76cd9c836d56752b', '0x23f13530fdb8f814cfc3f7f4f96b98e102b56b04',1718402231, '0x2b7af689e9ab7478c1ec463a198245682da1c2dbcceb911fcf79fa964aa2144e', '1', 20100000), +('0xe023f53f735c196e4a028233c2ee425957812a41', '0x5b93d80da1a359340d1f339fb574bdc56763f995',1718747603, '0xd0baeea2ca8d880137992a1f8f436273a9d55a2318221a4bb68d135205cc8e47', '1', 20100000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc1b19a08c2798c6930b8f3a44b7b0d08f4e198b8',1719459743, '0x58a53e9e87cc2ac7ff6a6d681cb7b14330a4e9eb4ab61c3961d048b6235a4f15', '10', 20200000), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', '0xc1b19a08c2798c6930b8f3a44b7b0d08f4e198b8',1719459755, '0x9666ffb735f3b37b55464f1515b77d37930d319fe415be80a1373796df8606ca', '8453', 20200000), +('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', '0x593786ce9f2962740d57f8eb1d5b53456b6c7c86',1719460643, '0x121617eea69f997f329f8a68c962982e391f73b4a5c53580eaa21902ac56329f', '324', 20200000), +('0xa8be6b2afe6e060985675675615c2108a66135c8', '0x3d03dc9b0a596bfa5e5c278c0886934b6416afaa',1719550055, '0xb2ddabdfaf0758670aa820981f2a32fe5157d0200ba5b8defed240102fb5f774', '1', 20200000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0x943c89e1fe0f8a507557d72d380e31ff01d19d88',1719902243, '0xe0bb4b158fe87d88167e5a645e7c7274b1fb1921990290b25ecf00f1c3d4538e', '56', 20200000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0x825c9bac60efb01eaa1da44bc2fb356638840f2c',1719902243, '0xe0bb4b158fe87d88167e5a645e7c7274b1fb1921990290b25ecf00f1c3d4538e', '10', 20200000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0x3d1a98b4e45c6f32f5c5b396abf5fd95bf30a4b9',1719902243, '0xe0bb4b158fe87d88167e5a645e7c7274b1fb1921990290b25ecf00f1c3d4538e', '8453', 20200000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0xae091d7e1fed989522125be65172cc1ac2969e6e',1719902243, '0xe0bb4b158fe87d88167e5a645e7c7274b1fb1921990290b25ecf00f1c3d4538e', '42161', 20200000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0x1d063e30c800d0165b3b2385c09fca8e96142deb',1719902243, '0xe0bb4b158fe87d88167e5a645e7c7274b1fb1921990290b25ecf00f1c3d4538e', '137', 20200000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0x0444d9aa9f0951cf513d2704e8b8454fa5e02aee',1719902243, '0xe0bb4b158fe87d88167e5a645e7c7274b1fb1921990290b25ecf00f1c3d4538e', '1', 20200000), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', '0xa9048585166f4f7c4589ade19567bb538035ed36',1719949955, '0x7a1c160870af8952879be73f6441b146618f55d09a9ce674e27d4961377fc05f', '1', 20200000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0xcae36eff002e34d9dded3541d293b64b6e0ded3c',1720437299, '0x204fa09239d2587a9ede5a2ee9cf40aed294389801b7b57312bf7c6a62093ecf', '1', 20300000), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', '0xa9048585166f4f7c4589ade19567bb538035ed36',1720467527, '0x0b3efa851a8fe211a4ab8b00f7b95809b452d7d3daff1ea7e2e0bf1719d58be6', '56', 20300000), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', '0xa9048585166f4f7c4589ade19567bb538035ed36',1720467563, '0x604f0603b209855346b6ad044e2ac7f8aef9fb9610830d54e0a4012aa2ff8eab', '137', 20300000), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', '0xa9048585166f4f7c4589ade19567bb538035ed36',1720467599, '0xf3ad585532dc811a438ba8b8e0f4a6624d5cdf5cfaef4dc9342bb7c11f2e5e29', '10', 20300000), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', '0xa9048585166f4f7c4589ade19567bb538035ed36',1720467623, '0xbf6e85b69b6480b4db54b26e8c431841e6cf337b0340e752f7d1a62ec9a2bd5e', '42161', 20300000), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', '0xa9048585166f4f7c4589ade19567bb538035ed36',1720467647, '0x2c620d5ee32125f82da91579b2bb70bb2354eed84c276c89e5c908c4d4fce7bc', '43114', 20300000), +('0xa8be6b2afe6e060985675675615c2108a66135c8', '0xb6613cc55866e282638006455390207c1d485be9',1721956019, '0x8a695a7b9264fef4c70b78df9b787989559f7a63916511faee79a667fb602163', '1', 20400000), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', '0xa9048585166f4f7c4589ade19567bb538035ed36',1722213431, '0xececd4a405b9b805ee804afbbd32d66768d649f22811e1c6d0f78522e6ceda24', '8453', 20400000), +('0x857851ee6e398651cb7c72462cc7ce2a94d8f1c6', '0x476c18a24a8593737521e99336750d0b6ea9e0dd',1723193987, '0x8f0e1f1f2c6c1db46c52121f1b1f38ff486a65682906ce8a6d2ddb09591cde3e', '56', 20500000), +('0x00e27f944460b61b659aa9919268e5b83d69c20a', '0x31df1df436d7815876aafff14e3bbfd616d55565',1723984703, '0xe50bb52cafa6a345cd26d65891090532b11f2b935f5a58fb4316a5fd38817ddb', '137', 20600000), +('0x00e27f944460b61b659aa9919268e5b83d69c20a', '0x93695b3079b2792f1fce01b7a1b420510ced3e85',1723984763, '0xd2a1a215a52965d033c459ab51728aa0c2e449eb4a95de5ead4f7a72f7419451', '42161', 20600000), +('0x857851ee6e398651cb7c72462cc7ce2a94d8f1c6', '0x509a3394c2d66c97e70a617556ed277ab3223378',1724028119, '0x32331b95b3ca6ebaa7c3ecd525ba466e56f3bcd4813886cb7d11f40d7a781b44', '1', 20600000), +('0x857851ee6e398651cb7c72462cc7ce2a94d8f1c6', '0x31df1df436d7815876aafff14e3bbfd616d55565',1724028191, '0x9d23a9f5b8a9fdd6c1460e6062c1d88c808edffd18cdbfe9b7ddd8b0cc8adbab', '137', 20600000), +('0x857851ee6e398651cb7c72462cc7ce2a94d8f1c6', '0x93695b3079b2792f1fce01b7a1b420510ced3e85',1724028227, '0x97c24e3bb56b99a36c9d1afd7060925b013baf1363f7ca9f663fe57cc642ecd8', '42161', 20600000), +('0xdcdf16a03360d4971ca4c1fd9967a47125f3c995', '0xa8c1c98aaf99a5dfc907d61b892b2ad624901185',1724294351, '0x0cfa3b71536bff882a99cc5896d5653b1f7438e313d5b91e9ec0ba74fa9b1957', '42161', 20600000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0xcdc43c82544bfadea3d48a7122c34aae672ec85e',1725239795, '0x7989295b5bd7b54e1258160b4c9e21311b718777505e66abfb098f8c58788f12', '42161', 20700000), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', '0x22863c875e6b7519141cb8394f2220fac7e6ade6',1725239795, '0x7989295b5bd7b54e1258160b4c9e21311b718777505e66abfb098f8c58788f12', '1', 20700000), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', '0xe94d917b2bebade1e49a0cf7a62884e542b3bddd',1727164619, '0x5b7d51188ae9101cf3cdc9fe354964929ffbdb4c5e3bde9672e89496ac192026', '1', 20800000); + +INSERT INTO promoteesName (promoter, name) VALUES ('0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a', 'Arctic Bastion'), +('0xd6ff6abb93ef058a474769f0d05c7fef440920f8', 'Swaap Labs'), +('0xe023f53f735c196e4a028233c2ee425957812a41', 'Seawise'), +('0xf63392356a985ead50b767a3e97a253ff870e91a', 'The 1inch Labs resolver'), +('0xdcdf16a03360d4971ca4c1fd9967a47125f3c995', 'Rizzolver'), +('0x5721898d36b15e19441ee2a403098ca187c92bb6', 'Flowmatic'), +('0x857851ee6e398651cb7c72462cc7ce2a94d8f1c6', 'Lumia'), +('0xd3eeebc3f13532fa4bccab0275da36a413ad101b', 'TrustedVolumes'), +('0xa8be6b2afe6e060985675675615c2108a66135c8', 'Alipo'), +('0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49', 'The T Resolver'), +('0x1113db6080ea2b9f92b2e9937ea712b3d730b3f1', 'Clipper'), +('0x05d18b713dab812c34edb48c76cd9c836d56752b', 'PropellerSwap'), +('0x12e5ceb5c14f3a1a9971da154f6530c1cf7274ac', 'Rosato L.L.C'); diff --git a/internal/app/server.go b/internal/app/server.go index 1e73da5..2b43957 100644 --- a/internal/app/server.go +++ b/internal/app/server.go @@ -29,11 +29,19 @@ var DuneKeyFlag = cli.StringFlag{ EnvVar: "DUNE_KEY", } +var HTTPPromoteeServerFlag = cli.StringFlag{ + Name: "promotee-server-address", + Usage: "Run the rest for promotees server", + EnvVar: "PROMOTEE_SERVER_ADDRESS", + Value: "localhost:8082", +} + func HTTPServerFlags() []cli.Flag { return []cli.Flag{ HTTPServerFlag, HTTPBackfillServerFlag, DuneURLFlag, DuneKeyFlag, + HTTPPromoteeServerFlag, } } diff --git a/internal/promotionworker/proworker.go b/internal/promotionworker/proworker.go new file mode 100644 index 0000000..2bb7bd9 --- /dev/null +++ b/internal/promotionworker/proworker.go @@ -0,0 +1,97 @@ +package promotionworker + +import ( + "context" + + "github.com/KyberNetwork/tradelogs/pkg/convert" + "github.com/KyberNetwork/tradelogs/pkg/evmlistenerclient" + "github.com/KyberNetwork/tradelogs/pkg/promotionparser" + "github.com/KyberNetwork/tradelogs/pkg/promotionstorage" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "go.uber.org/zap" +) + +type Proworker struct { + listener *evmlistenerclient.Client + l *zap.SugaredLogger + s *promotionstorage.Storage + p []promotionparser.Parser +} + +func New(l *zap.SugaredLogger, s *promotionstorage.Storage, listener *evmlistenerclient.Client, + parsers []promotionparser.Parser) *Proworker { + return &Proworker{ + listener: listener, + l: l, + s: s, + p: parsers, + } +} + +func (w *Proworker) Run(ctx context.Context) error { + for { + m, err := w.listener.GConsume(ctx) + if err != nil { + w.l.Errorw("Error while consume in group") + return err + } + w.l.Infow("process msg", "count", len(m)) + if len(m) == 0 { + continue + } + if err := w.processMessages(m); err != nil { + w.l.Errorw("Error when proccess msg", "error", err) + return err + } + if err := w.listener.Ack(ctx, m); err != nil { + w.l.Errorw("Error when ack msg", "error", err) + return err + } + } +} + +func (w *Proworker) processMessages(m []evmlistenerclient.Message) error { + for _, message := range m { + var ( + insertPromotees []promotionstorage.Promotee + deleteBlocks []uint64 + ) + for _, block := range message.NewBlocks { + for _, log := range block.Logs { + ethLog := convert.ToETHLog(log) + ps := w.findMatchingParser(ethLog) + if ps == nil { + continue + } + promotee, err := ps.Parse(ethLog, block.Timestamp) + if err != nil { + continue + } + insertPromotees = append(insertPromotees, promotee) + } + } + for _, block := range message.RevertedBlocks { + deleteBlocks = append(deleteBlocks, block.Number.Uint64()) + } + + if err := w.s.Delete(deleteBlocks); err != nil { + return err + } + if err := w.s.Insert(insertPromotees); err != nil { + return err + } + } + return nil +} + +func (w *Proworker) findMatchingParser(log ethTypes.Log) promotionparser.Parser { + var ps promotionparser.Parser + for _, p := range w.p { + if !p.LogFromContract(log) { + continue + } + ps = p + break + } + return ps +} diff --git a/internal/server/promotees/server.go b/internal/server/promotees/server.go new file mode 100644 index 0000000..91ce17e --- /dev/null +++ b/internal/server/promotees/server.go @@ -0,0 +1,80 @@ +package server + +import ( + "fmt" + "net/http" + "strings" + + "github.com/KyberNetwork/tradelogs/pkg/promotionstorage" + "github.com/gin-contrib/pprof" + "github.com/gin-gonic/gin" +) + +type Server struct { + r *gin.Engine + bindAddr string + s *promotionstorage.Storage +} + +func New(s *promotionstorage.Storage, bindAddr string) *Server { + engine := gin.New() + engine.Use(gin.Recovery()) + + server := &Server{ + r: engine, + bindAddr: bindAddr, + s: s, + } + + gin.SetMode(gin.DebugMode) + server.register() + + return server +} + +func (s *Server) Run() error { + if err := s.r.Run(s.bindAddr); err != nil { + return fmt.Errorf("run server: %w", err) + } + + return nil +} + +func (s *Server) register() { + pprof.Register(s.r, "/debug") + s.r.GET("/promotees", s.getPromotees) +} + +func responseErr(c *gin.Context, status int, err error) { + c.JSON(http.StatusBadRequest, gin.H{ + "success": false, + "error": err.Error(), + "status": status, + }) +} + +func (s *Server) getPromotees(c *gin.Context) { + var ( + query promotionstorage.PromoteesQuery + err = c.ShouldBind(&query) + ) + if query.Promotee != "" { + query.Promotee = strings.ToLower(query.Promotee) + } + if query.Promoter != "" { + query.Promoter = strings.ToLower(query.Promoter) + } + if err != nil { + responseErr(c, http.StatusBadRequest, err) + return + } + data, err := s.s.Get(query) + if err != nil { + responseErr(c, http.StatusBadRequest, err) + return + } + c.JSON(http.StatusOK, gin.H{ + "success": true, + "data": data, + }) +} diff --git a/pkg/evmlistenerclient/client.go b/pkg/evmlistenerclient/client.go index b273100..1c518bd 100644 --- a/pkg/evmlistenerclient/client.go +++ b/pkg/evmlistenerclient/client.go @@ -38,7 +38,7 @@ func New(l *zap.SugaredLogger, cfg Config, client redis.UniversalClient) *Client client: client, config: cfg, l: l, - groupName: "trading-tradelogs", + groupName: cfg.GroupName, } } diff --git a/pkg/promotionparser/oneinchv2/abi.json b/pkg/promotionparser/oneinchv2/abi.json new file mode 100644 index 0000000..077e05a --- /dev/null +++ b/pkg/promotionparser/oneinchv2/abi.json @@ -0,0 +1,342 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVotable", + "name": "token_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "resolverPercentageThreshold_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceLessThanThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "ETHTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfBounds", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "NotWhitelisted", + "type": "error" + }, + { + "inputs": [], + "name": "OutputArrayTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "PopFromEmptyArray", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SamePromotee", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "promoter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "promotee", + "type": "address" + } + ], + "name": "Promotion", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "Registered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "resolverPercentageThreshold", + "type": "uint256" + } + ], + "name": "ResolverPercentageThresholdSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "Unregistered", + "type": "event" + }, + { + "inputs": [], + "name": "BASIS_POINTS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clean", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "getPromotees", + "outputs": [ + { + "internalType": "address[]", + "name": "promotees", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWhitelist", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "promotee", + "type": "address" + } + ], + "name": "promote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "promotions", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "register", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rescueFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resolverPercentageThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resolverPercentageThreshold_", + "type": "uint256" + } + ], + "name": "setResolverPercentageThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IVotable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/pkg/promotionparser/oneinchv2/gen.sh b/pkg/promotionparser/oneinchv2/gen.sh new file mode 100755 index 0000000..68ecbaa --- /dev/null +++ b/pkg/promotionparser/oneinchv2/gen.sh @@ -0,0 +1 @@ +abigen --abi=abi.json --pkg=oneinchv2 --out=oneinchv2.go -type Promotion \ No newline at end of file diff --git a/pkg/promotionparser/oneinchv2/oneinchv2.go b/pkg/promotionparser/oneinchv2/oneinchv2.go new file mode 100644 index 0000000..5c9fb12 --- /dev/null +++ b/pkg/promotionparser/oneinchv2/oneinchv2.go @@ -0,0 +1,1236 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package oneinchv2 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// PromotionMetaData contains all meta data concerning the Promotion contract. +var PromotionMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIVotable\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"resolverPercentageThreshold_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BalanceLessThanThreshold\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ETHTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotWhitelisted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutputArrayTooSmall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PopFromEmptyArray\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SafeTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SamePromotee\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"promoter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"promotee\",\"type\":\"address\"}],\"name\":\"Promotion\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"Registered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"resolverPercentageThreshold\",\"type\":\"uint256\"}],\"name\":\"ResolverPercentageThresholdSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"Unregistered\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASIS_POINTS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clean\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"getPromotees\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"promotees\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWhitelist\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"promotee\",\"type\":\"address\"}],\"name\":\"promote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"promotions\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"rescueFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolverPercentageThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resolverPercentageThreshold_\",\"type\":\"uint256\"}],\"name\":\"setResolverPercentageThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIVotable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// PromotionABI is the input ABI used to generate the binding from. +// Deprecated: Use PromotionMetaData.ABI instead. +var PromotionABI = PromotionMetaData.ABI + +// Promotion is an auto generated Go binding around an Ethereum contract. +type Promotion struct { + PromotionCaller // Read-only binding to the contract + PromotionTransactor // Write-only binding to the contract + PromotionFilterer // Log filterer for contract events +} + +// PromotionCaller is an auto generated read-only Go binding around an Ethereum contract. +type PromotionCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PromotionTransactor is an auto generated write-only Go binding around an Ethereum contract. +type PromotionTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PromotionFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type PromotionFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PromotionSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type PromotionSession struct { + Contract *Promotion // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PromotionCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type PromotionCallerSession struct { + Contract *PromotionCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// PromotionTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type PromotionTransactorSession struct { + Contract *PromotionTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PromotionRaw is an auto generated low-level Go binding around an Ethereum contract. +type PromotionRaw struct { + Contract *Promotion // Generic contract binding to access the raw methods on +} + +// PromotionCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type PromotionCallerRaw struct { + Contract *PromotionCaller // Generic read-only contract binding to access the raw methods on +} + +// PromotionTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type PromotionTransactorRaw struct { + Contract *PromotionTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewPromotion creates a new instance of Promotion, bound to a specific deployed contract. +func NewPromotion(address common.Address, backend bind.ContractBackend) (*Promotion, error) { + contract, err := bindPromotion(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Promotion{PromotionCaller: PromotionCaller{contract: contract}, PromotionTransactor: PromotionTransactor{contract: contract}, PromotionFilterer: PromotionFilterer{contract: contract}}, nil +} + +// NewPromotionCaller creates a new read-only instance of Promotion, bound to a specific deployed contract. +func NewPromotionCaller(address common.Address, caller bind.ContractCaller) (*PromotionCaller, error) { + contract, err := bindPromotion(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PromotionCaller{contract: contract}, nil +} + +// NewPromotionTransactor creates a new write-only instance of Promotion, bound to a specific deployed contract. +func NewPromotionTransactor(address common.Address, transactor bind.ContractTransactor) (*PromotionTransactor, error) { + contract, err := bindPromotion(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PromotionTransactor{contract: contract}, nil +} + +// NewPromotionFilterer creates a new log filterer instance of Promotion, bound to a specific deployed contract. +func NewPromotionFilterer(address common.Address, filterer bind.ContractFilterer) (*PromotionFilterer, error) { + contract, err := bindPromotion(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PromotionFilterer{contract: contract}, nil +} + +// bindPromotion binds a generic wrapper to an already deployed contract. +func bindPromotion(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := PromotionMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Promotion *PromotionRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Promotion.Contract.PromotionCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Promotion *PromotionRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.Contract.PromotionTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Promotion *PromotionRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Promotion.Contract.PromotionTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Promotion *PromotionCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Promotion.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Promotion *PromotionTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Promotion *PromotionTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Promotion.Contract.contract.Transact(opts, method, params...) +} + +// BASISPOINTS is a free data retrieval call binding the contract method 0xe1f1c4a7. +// +// Solidity: function BASIS_POINTS() view returns(uint256) +func (_Promotion *PromotionCaller) BASISPOINTS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "BASIS_POINTS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BASISPOINTS is a free data retrieval call binding the contract method 0xe1f1c4a7. +// +// Solidity: function BASIS_POINTS() view returns(uint256) +func (_Promotion *PromotionSession) BASISPOINTS() (*big.Int, error) { + return _Promotion.Contract.BASISPOINTS(&_Promotion.CallOpts) +} + +// BASISPOINTS is a free data retrieval call binding the contract method 0xe1f1c4a7. +// +// Solidity: function BASIS_POINTS() view returns(uint256) +func (_Promotion *PromotionCallerSession) BASISPOINTS() (*big.Int, error) { + return _Promotion.Contract.BASISPOINTS(&_Promotion.CallOpts) +} + +// GetPromotees is a free data retrieval call binding the contract method 0xe5136e94. +// +// Solidity: function getPromotees(uint256 chainId) view returns(address[] promotees) +func (_Promotion *PromotionCaller) GetPromotees(opts *bind.CallOpts, chainId *big.Int) ([]common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "getPromotees", chainId) + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetPromotees is a free data retrieval call binding the contract method 0xe5136e94. +// +// Solidity: function getPromotees(uint256 chainId) view returns(address[] promotees) +func (_Promotion *PromotionSession) GetPromotees(chainId *big.Int) ([]common.Address, error) { + return _Promotion.Contract.GetPromotees(&_Promotion.CallOpts, chainId) +} + +// GetPromotees is a free data retrieval call binding the contract method 0xe5136e94. +// +// Solidity: function getPromotees(uint256 chainId) view returns(address[] promotees) +func (_Promotion *PromotionCallerSession) GetPromotees(chainId *big.Int) ([]common.Address, error) { + return _Promotion.Contract.GetPromotees(&_Promotion.CallOpts, chainId) +} + +// GetWhitelist is a free data retrieval call binding the contract method 0xd01f63f5. +// +// Solidity: function getWhitelist() view returns(address[]) +func (_Promotion *PromotionCaller) GetWhitelist(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "getWhitelist") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetWhitelist is a free data retrieval call binding the contract method 0xd01f63f5. +// +// Solidity: function getWhitelist() view returns(address[]) +func (_Promotion *PromotionSession) GetWhitelist() ([]common.Address, error) { + return _Promotion.Contract.GetWhitelist(&_Promotion.CallOpts) +} + +// GetWhitelist is a free data retrieval call binding the contract method 0xd01f63f5. +// +// Solidity: function getWhitelist() view returns(address[]) +func (_Promotion *PromotionCallerSession) GetWhitelist() ([]common.Address, error) { + return _Promotion.Contract.GetWhitelist(&_Promotion.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Promotion *PromotionCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Promotion *PromotionSession) Owner() (common.Address, error) { + return _Promotion.Contract.Owner(&_Promotion.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Promotion *PromotionCallerSession) Owner() (common.Address, error) { + return _Promotion.Contract.Owner(&_Promotion.CallOpts) +} + +// Promotions is a free data retrieval call binding the contract method 0x2af05166. +// +// Solidity: function promotions(address , uint256 ) view returns(address) +func (_Promotion *PromotionCaller) Promotions(opts *bind.CallOpts, arg0 common.Address, arg1 *big.Int) (common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "promotions", arg0, arg1) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Promotions is a free data retrieval call binding the contract method 0x2af05166. +// +// Solidity: function promotions(address , uint256 ) view returns(address) +func (_Promotion *PromotionSession) Promotions(arg0 common.Address, arg1 *big.Int) (common.Address, error) { + return _Promotion.Contract.Promotions(&_Promotion.CallOpts, arg0, arg1) +} + +// Promotions is a free data retrieval call binding the contract method 0x2af05166. +// +// Solidity: function promotions(address , uint256 ) view returns(address) +func (_Promotion *PromotionCallerSession) Promotions(arg0 common.Address, arg1 *big.Int) (common.Address, error) { + return _Promotion.Contract.Promotions(&_Promotion.CallOpts, arg0, arg1) +} + +// ResolverPercentageThreshold is a free data retrieval call binding the contract method 0x960462d1. +// +// Solidity: function resolverPercentageThreshold() view returns(uint256) +func (_Promotion *PromotionCaller) ResolverPercentageThreshold(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "resolverPercentageThreshold") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ResolverPercentageThreshold is a free data retrieval call binding the contract method 0x960462d1. +// +// Solidity: function resolverPercentageThreshold() view returns(uint256) +func (_Promotion *PromotionSession) ResolverPercentageThreshold() (*big.Int, error) { + return _Promotion.Contract.ResolverPercentageThreshold(&_Promotion.CallOpts) +} + +// ResolverPercentageThreshold is a free data retrieval call binding the contract method 0x960462d1. +// +// Solidity: function resolverPercentageThreshold() view returns(uint256) +func (_Promotion *PromotionCallerSession) ResolverPercentageThreshold() (*big.Int, error) { + return _Promotion.Contract.ResolverPercentageThreshold(&_Promotion.CallOpts) +} + +// Token is a free data retrieval call binding the contract method 0xfc0c546a. +// +// Solidity: function token() view returns(address) +func (_Promotion *PromotionCaller) Token(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "token") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Token is a free data retrieval call binding the contract method 0xfc0c546a. +// +// Solidity: function token() view returns(address) +func (_Promotion *PromotionSession) Token() (common.Address, error) { + return _Promotion.Contract.Token(&_Promotion.CallOpts) +} + +// Token is a free data retrieval call binding the contract method 0xfc0c546a. +// +// Solidity: function token() view returns(address) +func (_Promotion *PromotionCallerSession) Token() (common.Address, error) { + return _Promotion.Contract.Token(&_Promotion.CallOpts) +} + +// Clean is a paid mutator transaction binding the contract method 0xfc4333cd. +// +// Solidity: function clean() returns() +func (_Promotion *PromotionTransactor) Clean(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "clean") +} + +// Clean is a paid mutator transaction binding the contract method 0xfc4333cd. +// +// Solidity: function clean() returns() +func (_Promotion *PromotionSession) Clean() (*types.Transaction, error) { + return _Promotion.Contract.Clean(&_Promotion.TransactOpts) +} + +// Clean is a paid mutator transaction binding the contract method 0xfc4333cd. +// +// Solidity: function clean() returns() +func (_Promotion *PromotionTransactorSession) Clean() (*types.Transaction, error) { + return _Promotion.Contract.Clean(&_Promotion.TransactOpts) +} + +// Promote is a paid mutator transaction binding the contract method 0xf204bdb9. +// +// Solidity: function promote(uint256 chainId, address promotee) returns() +func (_Promotion *PromotionTransactor) Promote(opts *bind.TransactOpts, chainId *big.Int, promotee common.Address) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "promote", chainId, promotee) +} + +// Promote is a paid mutator transaction binding the contract method 0xf204bdb9. +// +// Solidity: function promote(uint256 chainId, address promotee) returns() +func (_Promotion *PromotionSession) Promote(chainId *big.Int, promotee common.Address) (*types.Transaction, error) { + return _Promotion.Contract.Promote(&_Promotion.TransactOpts, chainId, promotee) +} + +// Promote is a paid mutator transaction binding the contract method 0xf204bdb9. +// +// Solidity: function promote(uint256 chainId, address promotee) returns() +func (_Promotion *PromotionTransactorSession) Promote(chainId *big.Int, promotee common.Address) (*types.Transaction, error) { + return _Promotion.Contract.Promote(&_Promotion.TransactOpts, chainId, promotee) +} + +// Register is a paid mutator transaction binding the contract method 0x1aa3a008. +// +// Solidity: function register() returns() +func (_Promotion *PromotionTransactor) Register(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "register") +} + +// Register is a paid mutator transaction binding the contract method 0x1aa3a008. +// +// Solidity: function register() returns() +func (_Promotion *PromotionSession) Register() (*types.Transaction, error) { + return _Promotion.Contract.Register(&_Promotion.TransactOpts) +} + +// Register is a paid mutator transaction binding the contract method 0x1aa3a008. +// +// Solidity: function register() returns() +func (_Promotion *PromotionTransactorSession) Register() (*types.Transaction, error) { + return _Promotion.Contract.Register(&_Promotion.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Promotion *PromotionTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Promotion *PromotionSession) RenounceOwnership() (*types.Transaction, error) { + return _Promotion.Contract.RenounceOwnership(&_Promotion.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Promotion *PromotionTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Promotion.Contract.RenounceOwnership(&_Promotion.TransactOpts) +} + +// RescueFunds is a paid mutator transaction binding the contract method 0x78e3214f. +// +// Solidity: function rescueFunds(address token_, uint256 amount) returns() +func (_Promotion *PromotionTransactor) RescueFunds(opts *bind.TransactOpts, token_ common.Address, amount *big.Int) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "rescueFunds", token_, amount) +} + +// RescueFunds is a paid mutator transaction binding the contract method 0x78e3214f. +// +// Solidity: function rescueFunds(address token_, uint256 amount) returns() +func (_Promotion *PromotionSession) RescueFunds(token_ common.Address, amount *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.RescueFunds(&_Promotion.TransactOpts, token_, amount) +} + +// RescueFunds is a paid mutator transaction binding the contract method 0x78e3214f. +// +// Solidity: function rescueFunds(address token_, uint256 amount) returns() +func (_Promotion *PromotionTransactorSession) RescueFunds(token_ common.Address, amount *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.RescueFunds(&_Promotion.TransactOpts, token_, amount) +} + +// SetResolverPercentageThreshold is a paid mutator transaction binding the contract method 0xcfaa0951. +// +// Solidity: function setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) returns() +func (_Promotion *PromotionTransactor) SetResolverPercentageThreshold(opts *bind.TransactOpts, resolverPercentageThreshold_ *big.Int) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "setResolverPercentageThreshold", resolverPercentageThreshold_) +} + +// SetResolverPercentageThreshold is a paid mutator transaction binding the contract method 0xcfaa0951. +// +// Solidity: function setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) returns() +func (_Promotion *PromotionSession) SetResolverPercentageThreshold(resolverPercentageThreshold_ *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.SetResolverPercentageThreshold(&_Promotion.TransactOpts, resolverPercentageThreshold_) +} + +// SetResolverPercentageThreshold is a paid mutator transaction binding the contract method 0xcfaa0951. +// +// Solidity: function setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) returns() +func (_Promotion *PromotionTransactorSession) SetResolverPercentageThreshold(resolverPercentageThreshold_ *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.SetResolverPercentageThreshold(&_Promotion.TransactOpts, resolverPercentageThreshold_) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Promotion *PromotionTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Promotion *PromotionSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Promotion.Contract.TransferOwnership(&_Promotion.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Promotion *PromotionTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Promotion.Contract.TransferOwnership(&_Promotion.TransactOpts, newOwner) +} + +// PromotionOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Promotion contract. +type PromotionOwnershipTransferredIterator struct { + Event *PromotionOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionOwnershipTransferred represents a OwnershipTransferred event raised by the Promotion contract. +type PromotionOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Promotion *PromotionFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*PromotionOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &PromotionOwnershipTransferredIterator{contract: _Promotion.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Promotion *PromotionFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PromotionOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionOwnershipTransferred) + if err := _Promotion.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Promotion *PromotionFilterer) ParseOwnershipTransferred(log types.Log) (*PromotionOwnershipTransferred, error) { + event := new(PromotionOwnershipTransferred) + if err := _Promotion.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionPromotionIterator is returned from FilterPromotion and is used to iterate over the raw logs and unpacked data for Promotion events raised by the Promotion contract. +type PromotionPromotionIterator struct { + Event *PromotionPromotion // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionPromotionIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionPromotion) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionPromotion) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionPromotionIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionPromotionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionPromotion represents a Promotion event raised by the Promotion contract. +type PromotionPromotion struct { + Promoter common.Address + ChainId *big.Int + Promotee common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterPromotion is a free log retrieval operation binding the contract event 0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e. +// +// Solidity: event Promotion(address promoter, uint256 chainId, address promotee) +func (_Promotion *PromotionFilterer) FilterPromotion(opts *bind.FilterOpts) (*PromotionPromotionIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "Promotion") + if err != nil { + return nil, err + } + return &PromotionPromotionIterator{contract: _Promotion.contract, event: "Promotion", logs: logs, sub: sub}, nil +} + +// WatchPromotion is a free log subscription operation binding the contract event 0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e. +// +// Solidity: event Promotion(address promoter, uint256 chainId, address promotee) +func (_Promotion *PromotionFilterer) WatchPromotion(opts *bind.WatchOpts, sink chan<- *PromotionPromotion) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "Promotion") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionPromotion) + if err := _Promotion.contract.UnpackLog(event, "Promotion", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParsePromotion is a log parse operation binding the contract event 0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e. +// +// Solidity: event Promotion(address promoter, uint256 chainId, address promotee) +func (_Promotion *PromotionFilterer) ParsePromotion(log types.Log) (*PromotionPromotion, error) { + event := new(PromotionPromotion) + if err := _Promotion.contract.UnpackLog(event, "Promotion", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionRegisteredIterator is returned from FilterRegistered and is used to iterate over the raw logs and unpacked data for Registered events raised by the Promotion contract. +type PromotionRegisteredIterator struct { + Event *PromotionRegistered // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionRegisteredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionRegistered represents a Registered event raised by the Promotion contract. +type PromotionRegistered struct { + Addr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRegistered is a free log retrieval operation binding the contract event 0x2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e9. +// +// Solidity: event Registered(address addr) +func (_Promotion *PromotionFilterer) FilterRegistered(opts *bind.FilterOpts) (*PromotionRegisteredIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "Registered") + if err != nil { + return nil, err + } + return &PromotionRegisteredIterator{contract: _Promotion.contract, event: "Registered", logs: logs, sub: sub}, nil +} + +// WatchRegistered is a free log subscription operation binding the contract event 0x2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e9. +// +// Solidity: event Registered(address addr) +func (_Promotion *PromotionFilterer) WatchRegistered(opts *bind.WatchOpts, sink chan<- *PromotionRegistered) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "Registered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionRegistered) + if err := _Promotion.contract.UnpackLog(event, "Registered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRegistered is a log parse operation binding the contract event 0x2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e9. +// +// Solidity: event Registered(address addr) +func (_Promotion *PromotionFilterer) ParseRegistered(log types.Log) (*PromotionRegistered, error) { + event := new(PromotionRegistered) + if err := _Promotion.contract.UnpackLog(event, "Registered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionResolverPercentageThresholdSetIterator is returned from FilterResolverPercentageThresholdSet and is used to iterate over the raw logs and unpacked data for ResolverPercentageThresholdSet events raised by the Promotion contract. +type PromotionResolverPercentageThresholdSetIterator struct { + Event *PromotionResolverPercentageThresholdSet // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionResolverPercentageThresholdSetIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionResolverPercentageThresholdSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionResolverPercentageThresholdSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionResolverPercentageThresholdSetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionResolverPercentageThresholdSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionResolverPercentageThresholdSet represents a ResolverPercentageThresholdSet event raised by the Promotion contract. +type PromotionResolverPercentageThresholdSet struct { + ResolverPercentageThreshold *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterResolverPercentageThresholdSet is a free log retrieval operation binding the contract event 0xcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e. +// +// Solidity: event ResolverPercentageThresholdSet(uint256 resolverPercentageThreshold) +func (_Promotion *PromotionFilterer) FilterResolverPercentageThresholdSet(opts *bind.FilterOpts) (*PromotionResolverPercentageThresholdSetIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "ResolverPercentageThresholdSet") + if err != nil { + return nil, err + } + return &PromotionResolverPercentageThresholdSetIterator{contract: _Promotion.contract, event: "ResolverPercentageThresholdSet", logs: logs, sub: sub}, nil +} + +// WatchResolverPercentageThresholdSet is a free log subscription operation binding the contract event 0xcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e. +// +// Solidity: event ResolverPercentageThresholdSet(uint256 resolverPercentageThreshold) +func (_Promotion *PromotionFilterer) WatchResolverPercentageThresholdSet(opts *bind.WatchOpts, sink chan<- *PromotionResolverPercentageThresholdSet) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "ResolverPercentageThresholdSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionResolverPercentageThresholdSet) + if err := _Promotion.contract.UnpackLog(event, "ResolverPercentageThresholdSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseResolverPercentageThresholdSet is a log parse operation binding the contract event 0xcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e. +// +// Solidity: event ResolverPercentageThresholdSet(uint256 resolverPercentageThreshold) +func (_Promotion *PromotionFilterer) ParseResolverPercentageThresholdSet(log types.Log) (*PromotionResolverPercentageThresholdSet, error) { + event := new(PromotionResolverPercentageThresholdSet) + if err := _Promotion.contract.UnpackLog(event, "ResolverPercentageThresholdSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionUnregisteredIterator is returned from FilterUnregistered and is used to iterate over the raw logs and unpacked data for Unregistered events raised by the Promotion contract. +type PromotionUnregisteredIterator struct { + Event *PromotionUnregistered // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionUnregisteredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionUnregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionUnregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionUnregisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionUnregisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionUnregistered represents a Unregistered event raised by the Promotion contract. +type PromotionUnregistered struct { + Addr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnregistered is a free log retrieval operation binding the contract event 0x75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc. +// +// Solidity: event Unregistered(address addr) +func (_Promotion *PromotionFilterer) FilterUnregistered(opts *bind.FilterOpts) (*PromotionUnregisteredIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "Unregistered") + if err != nil { + return nil, err + } + return &PromotionUnregisteredIterator{contract: _Promotion.contract, event: "Unregistered", logs: logs, sub: sub}, nil +} + +// WatchUnregistered is a free log subscription operation binding the contract event 0x75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc. +// +// Solidity: event Unregistered(address addr) +func (_Promotion *PromotionFilterer) WatchUnregistered(opts *bind.WatchOpts, sink chan<- *PromotionUnregistered) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "Unregistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionUnregistered) + if err := _Promotion.contract.UnpackLog(event, "Unregistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUnregistered is a log parse operation binding the contract event 0x75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc. +// +// Solidity: event Unregistered(address addr) +func (_Promotion *PromotionFilterer) ParseUnregistered(log types.Log) (*PromotionUnregistered, error) { + event := new(PromotionUnregistered) + if err := _Promotion.contract.UnpackLog(event, "Unregistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/pkg/promotionparser/oneinchv2/oneinchv2_test.go b/pkg/promotionparser/oneinchv2/oneinchv2_test.go new file mode 100644 index 0000000..fec2935 --- /dev/null +++ b/pkg/promotionparser/oneinchv2/oneinchv2_test.go @@ -0,0 +1,62 @@ +package oneinchv2 + +import ( + "context" + "encoding/json" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +const rpcURL = "" + +func TestFetchEvent(t *testing.T) { + t.Skip() + p := MustNewParser() + require.Equal(t, p.abi.Events[PromotionEvent].ID, common.HexToHash("0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e")) + client, err := ethclient.Dial(rpcURL) + require.NoError(t, err) + logs, err := client.FilterLogs(context.Background(), ethereum.FilterQuery{ + BlockHash: nil, + FromBlock: big.NewInt(20583304), + ToBlock: big.NewInt(20583304), + Addresses: nil, + Topics: [][]common.Hash{{common.HexToHash("0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e")}}, + }) + require.NoError(t, err) + d, _ := json.Marshal(logs) + t.Log(string(d)) +} + +func TestParseEvent(t *testing.T) { + eventRaw := `{"address":"0xf55684bc536487394b423e70567413fab8e45e26", + "topics": [ + "0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e" + ], + "data":"0x000000000000000000000000dcdf16a03360d4971ca4c1fd9967a47125f3c995000000000000000000000000000000000000000000000000000000000000a4b1000000000000000000000000a8c1c98aaf99a5dfc907d61b892b2ad624901185", + "blockNumber":"0x13a1388", + "transactionHash":"0x0cfa3b71536bff882a99cc5896d5653b1f7438e313d5b91e9ec0ba74fa9b1957", + "transactionIndex":"0xac", + "blockHash":"0x016715ee70579c2023b59a14eb3b8911ff7bbb40198e0c0273e54470164bbff4", + "logIndex":"0x18d", + "removed":false + }` + event := types.Log{} + err := json.Unmarshal([]byte(eventRaw), &event) + require.NoError(t, err) + p := MustNewParser() + log, err := p.Parse(event, uint64(time.Now().Unix())) + require.NoError(t, err) + require.Equal(t, log.EventHash, p.eventHash) + t.Log("event hash", log.EventHash) + t.Log("promoter", log.Promoter) + t.Log("promotee", log.Promotee) + t.Log("chain id", log.ChainId) + // t.Log(log) +} diff --git a/pkg/promotionparser/oneinchv2/parser.go b/pkg/promotionparser/oneinchv2/parser.go new file mode 100644 index 0000000..efee488 --- /dev/null +++ b/pkg/promotionparser/oneinchv2/parser.go @@ -0,0 +1,89 @@ +package oneinchv2 + +import ( + "strings" + + ethereumTypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/KyberNetwork/tradelogs/pkg/promotionparser" + "github.com/KyberNetwork/tradelogs/pkg/promotionstorage" + "github.com/KyberNetwork/tradelogs/pkg/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +const ( + PromotionEvent = "Promotion" +) + +type Parser struct { + abi *abi.ABI + ps *PromotionFilterer + eventHash string +} + +func MustNewParser() *Parser { + ps, err := NewPromotionFilterer(common.Address{}, nil) + if err != nil { + panic(err) + } + ab, err := PromotionMetaData.GetAbi() + if err != nil { + panic(err) + } + promotionEvent, ok := ab.Events[PromotionEvent] + if !ok { + panic("no such event: Promotion") + } + return &Parser{ + ps: ps, + abi: ab, + eventHash: promotionEvent.ID.String(), + } +} + +func (p *Parser) Topics() []string { + return []string{ + p.eventHash, + } +} + +func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (promotionstorage.Promotee, error) { + if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { + return promotionstorage.Promotee{}, promotionparser.ErrInvalidTopic + } + e, err := p.ps.ParsePromotion(log) + if err != nil { + return promotionstorage.Promotee{}, err + } + res := promotionstorage.Promotee{ + Promoter: strings.ToLower(e.Promoter.String()), + ChainId: e.ChainId.String(), + Promotee: strings.ToLower(e.Promotee.String()), + Timestamp: blockTime * 1000, + EventHash: p.eventHash, + } + return res, nil +} + +func (p *Parser) Contract() string { + return promotionparser.Promotion1InchV2 +} + +func (p *Parser) UseTraceCall() bool { + return false +} + +func (p *Parser) ParseWithCallFrame(_ types.CallFrame, log ethereumTypes.Log, blockTime uint64) (promotionstorage.Promotee, error) { + return p.Parse(log, blockTime) +} + +func (p *Parser) LogFromContract(log ethereumTypes.Log) bool { + return strings.EqualFold(log.Address.String(), promotionparser.AddrPr1InchV2) && + len(log.Topics) > 0 && + strings.EqualFold(log.Topics[0].String(), p.eventHash) +} + +func (p *Parser) Address() string { + return promotionparser.AddrPr1InchV2 +} diff --git a/pkg/promotionparser/parser.go b/pkg/promotionparser/parser.go new file mode 100644 index 0000000..ffc5ba6 --- /dev/null +++ b/pkg/promotionparser/parser.go @@ -0,0 +1,31 @@ +package promotionparser + +import ( + "errors" + + "github.com/KyberNetwork/tradelogs/pkg/promotionstorage" + "github.com/KyberNetwork/tradelogs/pkg/types" + ethereumTypes "github.com/ethereum/go-ethereum/core/types" +) + +const ( + Promotion1InchV2 = "oneinchv2" + Promotion1InchV1 = "oneinchv1" + + AddrPr1InchV2 = "0xf55684bc536487394b423e70567413fab8e45e26" + AddrPr1InchV1 = "0xcb8308fcb7bc2f84ed1bea2c016991d34de5cc77" +) + +var ( + ErrInvalidTopic = errors.New("invalid order topic") +) + +type Parser interface { + Parse(log ethereumTypes.Log, blockTime uint64) (promotionstorage.Promotee, error) + Topics() []string + Contract() string + UseTraceCall() bool + ParseWithCallFrame(callFrame types.CallFrame, log ethereumTypes.Log, blockTime uint64) (promotionstorage.Promotee, error) + LogFromContract(log ethereumTypes.Log) bool + Address() string +} diff --git a/pkg/promotionstorage/storage_promotees.go b/pkg/promotionstorage/storage_promotees.go new file mode 100644 index 0000000..774c2ab --- /dev/null +++ b/pkg/promotionstorage/storage_promotees.go @@ -0,0 +1,124 @@ +package promotionstorage + +import ( + "fmt" + "reflect" + "strings" + + "github.com/Masterminds/squirrel" + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +const ( + promoteesTable = "promotees" + nameTable = "promoteesName" +) + +type EVMLog struct { + Address string `db:"address"` + Topics string `db:"topics"` + Data []byte `db:"data"` + BlockNumber uint64 `db:"block_number"` + TxHash string `db:"tx_hash"` + TxIndex uint `db:"tx_index"` + BlockHash string `db:"block_hash"` + Index uint `db:"log_index"` + Removed bool `db:"removed"` + Time uint64 `db:"time"` +} + +type Storage struct { + db *sqlx.DB + l *zap.SugaredLogger +} + +func New(l *zap.SugaredLogger, db *sqlx.DB) *Storage { + return &Storage{ + db: db, + l: l, + } +} + +func (s *Storage) Insert(promotees []Promotee) error { + if len(promotees) == 0 { + return nil + } + + b := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Insert(promoteesTable).Columns( + promoteesColumns()..., + ) + for _, promotee := range promotees { + b = b.Values( + promotee.SerializePromotees()..., + ) + } + q, p, err := b.Suffix("ON CONFLICT (promotee, promoter, chain_id) DO NOTHING").ToSql() + if err != nil { + s.l.Errorw("Error build insert", "error", err) + return err + } + if _, err := s.db.Exec(q, p...); err != nil { + s.l.Errorw("Error exec insert", "sql", q, "arg", p, "error", err) + return err + } + return nil +} + +func (s *Storage) Get(query PromoteesQuery) ([]Promotee, error) { + builder := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). + Select(fmt.Sprintf("%s.promoter, promotee, chain_id, event_hash, timestamp, name", promoteesTable)). + From(promoteesTable). + Join(fmt.Sprintf("%s ON %s.promoter = %s.promoter", nameTable, promoteesTable, nameTable)) + + v := reflect.ValueOf(query) + types := v.Type() + for i := 0; i < v.NumField(); i++ { + tag := string(types.Field(i).Tag.Get("form")) + if v.Field(i).IsZero() { + continue + } + builder = builder.Where(squirrel.Eq{tag: strings.ToLower(v.Field(i).String())}) + } + + q, p, err := builder.OrderBy(fmt.Sprintf("%s.timestamp DESC", promoteesTable)).ToSql() + if err != nil { + return nil, err + } + + var promotees []Promotee + if err := s.db.Select(&promotees, q, p...); err != nil { + return nil, err + } + + return promotees, nil +} + +func (s *Storage) Delete(blocks []uint64) error { + if len(blocks) == 0 { + return nil + } + q, p, err := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). + Delete(promoteesTable). + Where(squirrel.Eq{"block_number": blocks}). + ToSql() + if err != nil { + s.l.Errorw("Error while delete", "block_number", blocks, "error", err) + return err + } + if _, err := s.db.Exec(q, p...); err != nil { + return err + } + return nil +} + +func promoteesColumns() []string { + return []string{ + "promoter", + "promotee", + "timestamp", + "event_hash", + "chain_id", + "block_number", + } +} diff --git a/pkg/promotionstorage/storage_test.go b/pkg/promotionstorage/storage_test.go new file mode 100644 index 0000000..30ef78b --- /dev/null +++ b/pkg/promotionstorage/storage_test.go @@ -0,0 +1,58 @@ +package promotionstorage + +import ( + "encoding/json" + "os" + "testing" + + "github.com/KyberNetwork/tradelogs/internal/testutil" + "github.com/test-go/testify/assert" + "go.uber.org/zap" +) + +func TestInsert(t *testing.T) { + db, tearDown := testutil.MustNewDevelopmentDB("../../cmd/promotees/migrations") + l := zap.S() + defer func() { + assert.NoError(t, tearDown()) + }() + s := New(l, db) + var promotees []Promotee + byteValue, err := os.Open("test.json") + + assert.NoError(t, err) + assert.NoError(t, json.NewDecoder(byteValue).Decode(&promotees), "failed to parse promotees") + assert.NoError(t, s.Insert(promotees), "failed to insert promotees") + for _, promotee := range promotees { + t.Log(promotee) + } + + // byteValue2, err := os.Open("test2.json") + + // assert.NoError(t, err) + // assert.NoError(t, json.NewDecoder(byteValue2).Decode(&promotees), "failed to parse promotees") + // assert.NoError(t, s.Insert(promotees), "failed to insert promotees") + // t.Log(promotees) + var query PromoteesQuery + query.Promoter = "" + query.Promotee = "" + query.ChainId = "" + pwithname, err := s.Get(query) + + assert.NoError(t, err, "Failed to get promotees") + + for _, p := range pwithname { + t.Log(p) + } + blocks := []uint64{3} + err = s.Delete(blocks) + assert.NoError(t, err, "Failed to delete") + + pwithname, err = s.Get(query) + + assert.NoError(t, err, "Failed to get promotees") + + for _, p := range pwithname { + t.Log(p) + } +} diff --git a/pkg/promotionstorage/test.json b/pkg/promotionstorage/test.json new file mode 100644 index 0000000..a71dde7 --- /dev/null +++ b/pkg/promotionstorage/test.json @@ -0,0 +1,34 @@ +[ + { + "promoter": "0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49", + "promotee": "0x1e9d349cec77fea6481f009593101d0e20a69490", + "timestamp": 498529484, + "event_hash": "0xf8cf20ddcd5eaf81ea4967c60402d1f3805804126fd4371bf9e39a7605ccad02", + "chain_id": "1", + "block_number": 1 + }, + { + "promoter": "0xe023f53f735c196e4a028233c2ee425957812a41", + "promotee": "0xd1742b3c4fbb096990c8950fa635aec75b30781a", + "timestamp": 498539324, + "event_hash": "0x4dc9aa484e1afe6f9e01280925504841c26a81e0db09c6406ca7b1869bdc6ea8", + "chain_id": "2", + "block_number": 2 + }, + { + "promoter": "0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a", + "promotee": "0x0b8a49d816cc709b6eadb09498030ae3416b66dc", + "timestamp": 498539524, + "event_hash": "0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b", + "chain_id": "1", + "block_number": 3 + }, + { + "promoter": "0xe023f53f735c196e4a028233c2ee425957812a41", + "promotee": "0x01372be9616ff00469d3e509b77d6960af757180", + "timestamp": 4985437524, + "event_hash": "0x46ab12e2cb6e5e7c2a1e0a1da7735785b713124aeb93ba3093e64ed69451e624", + "chain_id": "2", + "block_number": 4 + } +] \ No newline at end of file diff --git a/pkg/promotionstorage/test2.json b/pkg/promotionstorage/test2.json new file mode 100644 index 0000000..fe5a5cc --- /dev/null +++ b/pkg/promotionstorage/test2.json @@ -0,0 +1,42 @@ +[ + { + "promoter": "0xd7f6f541d4210550ca56f7b4c4a549efd4cafb49", + "promotee": "0x1e9d349cec77fea6481f009593101d0e20a69490", + "timestamp": 498529484, + "event_hash": "0xf8cf20ddcd5eaf81ea4967c60402d1f3805804126fd4371bf9e39a7605ccad02", + "chain_id": "1", + "block_number": 1 + }, + { + "promoter": "0xe023f53f735c196e4a028233c2ee425957812a41", + "promotee": "0xd1742b3c4fbb096990c8950fa635aec75b30781a", + "timestamp": 498539324, + "event_hash": "0x4dc9aa484e1afe6f9e01280925504841c26a81e0db09c6406ca7b1869bdc6ea8", + "chain_id": "2", + "block_number": 2 + }, + { + "promoter": "0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a", + "promotee": "0x0b8a49d816cc709b6eadb09498030ae3416b66dc", + "timestamp": 498539524, + "event_hash": "0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b", + "chain_id": "1", + "block_number": 3 + }, + { + "promoter": "0xa260f8b7c8f37c2f1bc11b04c19902829de6ac8a", + "promotee": "0x0b8a49d816cc709b6eadb09498030ae3416b66dc", + "timestamp": 498539524, + "event_hash": "0xeb0bd6036ef28377b2288e0d1fb38c064c14635085777c6e88c617f9b21ac85b", + "chain_id": "2", + "block_number": 3 + }, + { + "promoter": "0xe023f53f735c196e4a028233c257812a41", + "promotee": "0x01372be9616ff00469d3e509b77d6daf757180", + "timestamp": 4985437524, + "event_hash": "0x46ab12e2cb6e5e7c2a1e0a1da7735785b713124aeb93ba3093e64ed69451e624", + "chain_id": "2", + "block_number": 4 + } +] \ No newline at end of file diff --git a/pkg/promotionstorage/types.go b/pkg/promotionstorage/types.go new file mode 100644 index 0000000..f22a574 --- /dev/null +++ b/pkg/promotionstorage/types.go @@ -0,0 +1,32 @@ +package promotionstorage + +import ( + "strings" +) + +type Promotee struct { + Promoter string `db:"promoter" json:"promoter,omitempty"` + Promotee string `db:"promotee" json:"promotee,omitempty"` + Timestamp uint64 `db:"timestamp" json:"timestamp,omitempty"` + EventHash string `db:"event_hash" json:"event_hash,omitempty"` + ChainId string `db:"chain_id" json:"chain_id,omitempty"` + BlockNumber uint64 `db:"block_number" json:"block_number,omitempty"` + Name string `db:"name" json:"name,omitempty"` +} + +type PromoteesQuery struct { + Promoter string `form:"promoter" json:"promoter,omitempty"` + Promotee string `form:"promotee" json:"promotee,omitempty"` + ChainId string `form:"chain_id" json:"chain_id,omitempty"` +} + +func (o *Promotee) SerializePromotees() []interface{} { + return []interface{}{ + strings.ToLower(o.Promoter), + strings.ToLower(o.Promotee), + o.Timestamp, + o.EventHash, + o.ChainId, + o.BlockNumber, + } +} diff --git a/v2/cmd/backfill/main.go b/v2/cmd/backfill/main.go index 5afe9a6..dc6e73b 100644 --- a/v2/cmd/backfill/main.go +++ b/v2/cmd/backfill/main.go @@ -13,8 +13,11 @@ import ( "github.com/KyberNetwork/tradelogs/v2/pkg/kafka" "github.com/KyberNetwork/tradelogs/v2/pkg/parser" "github.com/KyberNetwork/tradelogs/v2/pkg/parser/zxotc" + "github.com/KyberNetwork/tradelogs/v2/pkg/promotionparser" + "github.com/KyberNetwork/tradelogs/v2/pkg/promotionparser/oneinchv2" "github.com/KyberNetwork/tradelogs/v2/pkg/rpcnode" "github.com/KyberNetwork/tradelogs/v2/pkg/storage/backfill" + promoteeTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/promotees" "github.com/KyberNetwork/tradelogs/v2/pkg/storage/state" "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs" storageTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs/types" @@ -65,6 +68,9 @@ func run(c *cli.Context) error { } manager := tradelogs.NewManager(l, storages) + //promotion storage + proStorage := promoteeTypes.New(l, db) + // backfill storage backfillStorage := backfill.New(l, db) @@ -100,6 +106,8 @@ func run(c *cli.Context) error { //zxrfqv3.MustNewParserWithDeployer(traceCalls, ethClient, common.HexToAddress(parser.Deployer0xV3)), } + proParsers := []promotionparser.Parser{oneinchv2.MustNewParser()} + // kafka broadcast topic broadcastTopic := c.String(libapp.KafkaBroadcastTopic.Name) err = kafka.ValidateTopicName(broadcastTopic) @@ -114,7 +122,7 @@ func run(c *cli.Context) error { } // trade log handler - tradeLogHandler := handler.NewTradeLogHandler(l, rpcNode, manager, parsers, broadcastTopic, kafkaPublisher) + tradeLogHandler := handler.NewTradeLogHandler(l, rpcNode, manager, proStorage, parsers, proParsers, broadcastTopic, kafkaPublisher) // parse log worker w := worker.NewBackFiller(tradeLogHandler, backfillStorage, stateStorage, l, rpcNode, parsers) diff --git a/v2/cmd/parse_log/main.go b/v2/cmd/parse_log/main.go index 56730d5..f0f24ba 100644 --- a/v2/cmd/parse_log/main.go +++ b/v2/cmd/parse_log/main.go @@ -14,7 +14,10 @@ import ( "github.com/KyberNetwork/tradelogs/v2/pkg/kafka" "github.com/KyberNetwork/tradelogs/v2/pkg/parser" "github.com/KyberNetwork/tradelogs/v2/pkg/parser/zxotc" + "github.com/KyberNetwork/tradelogs/v2/pkg/promotionparser" + pro1inchv2 "github.com/KyberNetwork/tradelogs/v2/pkg/promotionparser/oneinchv2" "github.com/KyberNetwork/tradelogs/v2/pkg/rpcnode" + promoteeTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/promotees" "github.com/KyberNetwork/tradelogs/v2/pkg/storage/state" "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs" storageTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs/types" @@ -63,6 +66,10 @@ func run(c *cli.Context) error { manager := tradelogs.NewManager(l, []storageTypes.Storage{ zxotcStorage.New(l, db), }) + + //promotion storage + proStorage := promoteeTypes.New(l, db) + // state storage s := state.New(l, db) @@ -95,6 +102,8 @@ func run(c *cli.Context) error { //zxrfqv3.MustNewParserWithDeployer(traceCalls, ethClient, common.HexToAddress(parser.Deployer0xV3)), } + proParsers := []promotionparser.Parser{pro1inchv2.MustNewParser()} + // kafka broadcast topic broadcastTopic := c.String(libapp.KafkaBroadcastTopic.Name) err = kafka.ValidateTopicName(broadcastTopic) @@ -109,7 +118,7 @@ func run(c *cli.Context) error { } // trade log handler - tradeLogHandler := handler.NewTradeLogHandler(l, rpcNode, manager, parsers, broadcastTopic, kafkaPublisher) + tradeLogHandler := handler.NewTradeLogHandler(l, rpcNode, manager, proStorage, parsers, proParsers, broadcastTopic, kafkaPublisher) // parse log worker w := worker.NewParseLog(tradeLogHandler, s, l) diff --git a/v2/cmd/promotees/main.go b/v2/cmd/promotees/main.go new file mode 100644 index 0000000..109e922 --- /dev/null +++ b/v2/cmd/promotees/main.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + "log" + "os" + + proServer "github.com/KyberNetwork/tradelogs/v2/internal/server/promotees" + libapp "github.com/KyberNetwork/tradelogs/v2/pkg/app" + promoteeTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/promotees" + "github.com/KyberNetwork/tradinglib/pkg/dbutil" + "github.com/jmoiron/sqlx" + "github.com/urfave/cli" + "go.uber.org/zap" +) + +func main() { + app := libapp.NewApp() + app.Name = "promotees service" + app.Action = run + + app.Flags = append(app.Flags, libapp.PostgresSQLFlags("tradelogs_v2")...) + app.Flags = append(app.Flags, libapp.HTTPServerFlags()...) + + if err := app.Run(os.Args); err != nil { + log.Panic(err) + } +} + +func run(c *cli.Context) error { + logger, _, flush, err := libapp.NewLogger(c) + if err != nil { + return fmt.Errorf("new logger: %w", err) + } + + defer flush() + + zap.ReplaceGlobals(logger) + l := logger.Sugar() + l.Infow("Starting backfill service") + + db, err := initDB(c) + l.Infow("init db successfully") + if err != nil { + return fmt.Errorf("cannot init DB: %w", err) + } + + //promotion storage + proStorage := promoteeTypes.New(l, db) + + s := proServer.New(proStorage, c.String(libapp.HTTPPromoteeServerFlag.Name)) + + return s.Run() +} + +func initDB(c *cli.Context) (*sqlx.DB, error) { + db, err := libapp.NewDB(map[string]interface{}{ + "host": c.String(libapp.PostgresHost.Name), + "port": c.Int(libapp.PostgresPort.Name), + "user": c.String(libapp.PostgresUser.Name), + "password": c.String(libapp.PostgresPassword.Name), + "dbname": c.String(libapp.PostgresDatabase.Name), + "sslmode": "disable", + }) + if err != nil { + return nil, err + } + + _, err = dbutil.RunMigrationUp(db.DB, c.String(libapp.PostgresMigrationPath.Name), + c.String(libapp.PostgresDatabase.Name)) + if err != nil { + return nil, err + } + return db, nil +} diff --git a/v2/internal/server/promotees/server.go b/v2/internal/server/promotees/server.go new file mode 100644 index 0000000..fe450f0 --- /dev/null +++ b/v2/internal/server/promotees/server.go @@ -0,0 +1,116 @@ +package server + +import ( + "fmt" + "net/http" + "strings" + + promoteeTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/promotees" + "github.com/gin-contrib/pprof" + "github.com/gin-gonic/gin" +) + +type Server struct { + r *gin.Engine + bindAddr string + s *promoteeTypes.Storage +} + +func New(s *promoteeTypes.Storage, bindAddr string) *Server { + engine := gin.New() + engine.Use(gin.Recovery()) + + server := &Server{ + r: engine, + bindAddr: bindAddr, + s: s, + } + + gin.SetMode(gin.DebugMode) + server.register() + + return server +} + +func (s *Server) Run() error { + if err := s.r.Run(s.bindAddr); err != nil { + return fmt.Errorf("run server: %w", err) + } + + return nil +} + +func (s *Server) register() { + pprof.Register(s.r, "/debug") + s.r.GET("/promotees", s.getPromotees) + s.r.POST("/insert_name", s.insertName) +} + +func responseErr(c *gin.Context, status int, err error) { + c.JSON(http.StatusBadRequest, gin.H{ + "success": false, + "error": err.Error(), + "status": status, + }) +} + +func (s *Server) getPromotees(c *gin.Context) { + var ( + query promoteeTypes.PromoteesQuery + err = c.ShouldBind(&query) + ) + if err != nil { + responseErr(c, http.StatusBadRequest, err) + return + } + if query.Promotee != "" { + query.Promotee = strings.ToLower(query.Promotee) + } + if query.Promoter != "" { + query.Promoter = strings.ToLower(query.Promoter) + } + data, err := s.s.Get(query) + if err != nil { + responseErr(c, http.StatusBadRequest, err) + return + } + c.JSON(http.StatusOK, gin.H{ + "success": true, + "data": data, + }) +} + +func (s *Server) insertName(c *gin.Context) { + var queries []promoteeTypes.PromoteesQuery + + if err := c.ShouldBindJSON(&queries); err != nil { + responseErr(c, http.StatusBadRequest, err) + return + } + + promotees := make([]promoteeTypes.Promotee, len(queries)) + for i, query := range queries { + if query.Name == "" { + responseErr(c, http.StatusBadRequest, fmt.Errorf("missing field 'Name' in query index %d", i)) + return + } + if query.Promoter == "" { + responseErr(c, http.StatusBadRequest, fmt.Errorf("missing field 'Promoter' in query index %d", i)) + return + } + promotees[i] = promoteeTypes.Promotee{ + Promoter: strings.ToLower(query.Promoter), + Name: query.Name, + } + } + + if err := s.s.InsertPromoterName(promotees); err != nil { + responseErr(c, http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, gin.H{ + "success": true, + "data": promotees, + }) +} diff --git a/v2/internal/worker/log_parser.go b/v2/internal/worker/log_parser.go index 27f1f87..99fc5c0 100644 --- a/v2/internal/worker/log_parser.go +++ b/v2/internal/worker/log_parser.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "time" "github.com/KyberNetwork/evmlistener/pkg/types" "github.com/KyberNetwork/tradelogs/v2/pkg/handler" @@ -49,8 +50,9 @@ func (w *LogParser) processMessage(msg types.Message) error { for _, block := range msg.NewBlocks { blockNumber := block.Number.Uint64() - + time.Sleep(2 * time.Second) err := w.handler.ProcessBlock(block.Hash, blockNumber, block.Timestamp) + if err != nil { return fmt.Errorf("failed to process new block: %w", err) } diff --git a/v2/pkg/app/server.go b/v2/pkg/app/server.go index 0225d0f..bba8640 100644 --- a/v2/pkg/app/server.go +++ b/v2/pkg/app/server.go @@ -9,8 +9,16 @@ var HTTPBackfillServerFlag = cli.StringFlag{ Value: "localhost:8081", } +var HTTPPromoteeServerFlag = cli.StringFlag{ + Name: "promotee-server-address", + Usage: "Run the rest for promotees server", + EnvVar: "PROMOTEE_SERVER_ADDRESS", + Value: "localhost:8082", +} + func HTTPServerFlags() []cli.Flag { return []cli.Flag{ HTTPBackfillServerFlag, + HTTPPromoteeServerFlag, } } diff --git a/v2/pkg/constant/exchange.go b/v2/pkg/constant/exchange.go index 5f975e6..e061694 100644 --- a/v2/pkg/constant/exchange.go +++ b/v2/pkg/constant/exchange.go @@ -30,4 +30,10 @@ const ( Deployer0xV3 = "0x00000000000004533Fe15556B1E086BB1A72cEae" TableZeroX = "tradelogs_zerox" + + Promotion1InchV2 = "oneinchv2" + Promotion1InchV1 = "oneinchv1" + + AddrPr1InchV2 = "0xf55684bc536487394b423e70567413fab8e45e26" + AddrPr1InchV1 = "0xcb8308fcb7bc2f84ed1bea2c016991d34de5cc77" ) diff --git a/v2/pkg/handler/trade_logs.go b/v2/pkg/handler/trade_logs.go index 6c958c3..43e02ce 100644 --- a/v2/pkg/handler/trade_logs.go +++ b/v2/pkg/handler/trade_logs.go @@ -7,7 +7,9 @@ import ( "github.com/KyberNetwork/tradelogs/v2/pkg/kafka" "github.com/KyberNetwork/tradelogs/v2/pkg/parser" + "github.com/KyberNetwork/tradelogs/v2/pkg/promotionparser" "github.com/KyberNetwork/tradelogs/v2/pkg/rpcnode" + promoteeTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/promotees" "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs" storageTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs/types" "github.com/KyberNetwork/tradelogs/v2/pkg/types" @@ -19,12 +21,14 @@ import ( ) type TradeLogHandler struct { - l *zap.SugaredLogger - rpcClient rpcnode.IClient - storage *tradelogs.Manager - parsers []parser.Parser - kafkaTopic string - publisher kafka.Publisher + l *zap.SugaredLogger + rpcClient rpcnode.IClient + storage *tradelogs.Manager + promoteestorage *promoteeTypes.Storage + parsers []parser.Parser + promotionparsers []promotionparser.Parser + kafkaTopic string + publisher kafka.Publisher } type logMetadata struct { @@ -35,15 +39,19 @@ type logMetadata struct { timestamp uint64 } -func NewTradeLogHandler(l *zap.SugaredLogger, rpc rpcnode.IClient, storage *tradelogs.Manager, parsers []parser.Parser, +func NewTradeLogHandler(l *zap.SugaredLogger, rpc rpcnode.IClient, + storage *tradelogs.Manager, proStorage *promoteeTypes.Storage, + parsers []parser.Parser, proParsers []promotionparser.Parser, kafkaTopic string, publisher kafka.Publisher) *TradeLogHandler { return &TradeLogHandler{ - l: l, - rpcClient: rpc, - storage: storage, - parsers: parsers, - kafkaTopic: kafkaTopic, - publisher: publisher, + l: l, + rpcClient: rpc, + storage: storage, + promoteestorage: proStorage, + parsers: parsers, + promotionparsers: proParsers, + kafkaTopic: kafkaTopic, + publisher: publisher, } } @@ -60,10 +68,24 @@ func (h *TradeLogHandler) ProcessBlockWithExclusion(blockHash string, blockNumbe // fetch trace call calls, err := h.rpcClient.FetchTraceCalls(context.Background(), blockHash) + if err != nil { return fmt.Errorf("fetch calls error: %w", err) } + err = h.processForTradelog(calls, blockHash, blockNumber, timestamp, exclusions) + if err != nil { + return fmt.Errorf("error when process block: %d", blockNumber) + } + + err = h.processForPromotion(calls, blockHash, blockNumber, timestamp) + if err != nil { + return fmt.Errorf("error when process block: %d", blockNumber) + } + + return nil +} +func (h *TradeLogHandler) processForTradelog(calls []types.TransactionCallFrame, blockHash string, blockNumber uint64, timestamp uint64, exclusions sets.Set[string]) error { logIndexStart := 0 for i, call := range calls { logIndexStart = assignLogIndexes(&call.CallFrame, logIndexStart) @@ -75,7 +97,7 @@ func (h *TradeLogHandler) ProcessBlockWithExclusion(blockHash string, blockNumbe timestamp: timestamp, } - tradeLogs := h.processCallFrame(call.CallFrame, metadata, exclusions) + tradeLogs := h.processCallFrameForTradelog(call.CallFrame, metadata, exclusions) if len(tradeLogs) == 0 { continue } @@ -85,7 +107,7 @@ func (h *TradeLogHandler) ProcessBlockWithExclusion(blockHash string, blockNumbe tradeLogs[j].InteractContract = call.CallFrame.To } - err = h.storage.Insert(tradeLogs) + err := h.storage.Insert(tradeLogs) if err != nil { return fmt.Errorf("write to storage error: %w", err) } @@ -114,16 +136,42 @@ func (h *TradeLogHandler) ProcessBlockWithExclusion(blockHash string, blockNumbe } h.l.Infow("successfully process block", "blockNumber", blockNumber) + return nil +} + +func (h *TradeLogHandler) processForPromotion(calls []types.TransactionCallFrame, blockHash string, blockNumber uint64, timestamp uint64) error { + for i, call := range calls { + metadata := logMetadata{ + blockNumber: blockNumber, + blockHash: blockHash, + txHash: call.TxHash, + txIndex: i, + timestamp: timestamp, + } + promotees := h.processCallFrameForPromotion(call.CallFrame, metadata) + if len(promotees) == 0 { + continue + } + + err := h.promoteestorage.Insert(promotees) + if err != nil { + return fmt.Errorf("write to storage error: %w", err) + } + h.l.Infow("successfully insert promotees", "blockNumber", blockNumber) + + } + + h.l.Infow("successfully process block", "blockNumber", blockNumber) return nil } -func (h *TradeLogHandler) processCallFrame(call types.CallFrame, metadata logMetadata, exclusions sets.Set[string]) []storageTypes.TradeLog { +func (h *TradeLogHandler) processCallFrameForTradelog(call types.CallFrame, metadata logMetadata, exclusions sets.Set[string]) []storageTypes.TradeLog { result := make([]storageTypes.TradeLog, 0) // process the sub trace calls for _, traceCall := range call.Calls { - tradeLogs := h.processCallFrame(traceCall, metadata, exclusions) + tradeLogs := h.processCallFrameForTradelog(traceCall, metadata, exclusions) result = append(result, tradeLogs...) } @@ -157,6 +205,44 @@ func (h *TradeLogHandler) processCallFrame(call types.CallFrame, metadata logMet return result } +func (h *TradeLogHandler) processCallFrameForPromotion(call types.CallFrame, metadata logMetadata) []promoteeTypes.Promotee { + result := make([]promoteeTypes.Promotee, 0) + + // process the sub trace calls + for _, traceCall := range call.Calls { + promotees := h.processCallFrameForPromotion(traceCall, metadata) + result = append(result, promotees...) + } + + // process current trace call + for _, log := range call.Logs { + ethLog := ethereumTypes.Log{ + Address: log.Address, + Topics: log.Topics, + Data: common.FromHex(log.Data), + TxIndex: uint(metadata.txIndex), + TxHash: common.HexToHash(metadata.txHash), + BlockHash: common.HexToHash(metadata.blockHash), + BlockNumber: metadata.blockNumber, + Index: uint(log.Index), + } + // find the corresponding promotion parser + p := h.findMatchingPromotionParser(ethLog) + if p == nil { + continue + } + + // parse + promotee, err := p.ParseWithCallFrame(call, ethLog, metadata.timestamp) + if err != nil { + h.l.Errorw("error when parse log", "log", ethLog, "err", err, "parser", p.Contract()) + continue + } + result = append(result, promotee) + } + return result +} + func (h *TradeLogHandler) findMatchingParser(log ethereumTypes.Log) parser.Parser { for _, p := range h.parsers { if p.LogFromExchange(log) { @@ -166,6 +252,15 @@ func (h *TradeLogHandler) findMatchingParser(log ethereumTypes.Log) parser.Parse return nil } +func (h *TradeLogHandler) findMatchingPromotionParser(log ethereumTypes.Log) promotionparser.Parser { + for _, p := range h.promotionparsers { + if p.LogFromContract(log) { + return p + } + } + return nil +} + func (h *TradeLogHandler) RevertBlock(blocks []uint64) error { if len(blocks) == 0 { return nil @@ -176,6 +271,11 @@ func (h *TradeLogHandler) RevertBlock(blocks []uint64) error { return fmt.Errorf("delete blocks error: %w", err) } + err = h.promoteestorage.Delete((blocks)) + if err != nil { + return fmt.Errorf("delete blocks error: %w", err) + } + msgBytes, err := json.Marshal(kafka.Message{ Type: kafka.MessageTypeRevert, Data: blocks, diff --git a/v2/pkg/handler/trade_logs_test.go b/v2/pkg/handler/trade_logs_test.go index e4ef3fd..fd14109 100644 --- a/v2/pkg/handler/trade_logs_test.go +++ b/v2/pkg/handler/trade_logs_test.go @@ -5,17 +5,11 @@ import ( "os" "testing" - "github.com/KyberNetwork/tradelogs/v2/mocks" - "github.com/KyberNetwork/tradelogs/v2/pkg/parser" - zxotc2 "github.com/KyberNetwork/tradelogs/v2/pkg/parser/zxotc" "github.com/KyberNetwork/tradelogs/v2/pkg/rpcnode" - "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs" - "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs/types" types2 "github.com/KyberNetwork/tradelogs/v2/pkg/types" types3 "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" "go.uber.org/zap" ) @@ -24,32 +18,32 @@ var rpcURL = os.Getenv("TEST_RPC_URL") func TestTradeLogHandler_ProcessBlock(t *testing.T) { t.Skip("Need to set the rpc url env that enables the trace call JSON-RPC") - ethClient, err := ethclient.Dial(rpcURL) - if err != nil { - t.Fatal(err) - } - client := rpcnode.NewClient(zap.S(), ethClient) + // ethClient, err := ethclient.Dial(rpcURL) + // if err != nil { + // t.Fatal(err) + // } + // client := rpcnode.NewClient(zap.S(), ethClient) - mockStorage := &mocks.MockStorage{} - mockStorage.On("Exchange").Return("zerox"). - On("Insert", mock.Anything).Return(nil). - On("Delete", mock.Anything).Return(nil) - s := tradelogs.NewManager(zap.S(), []types.Storage{mockStorage}) + // mockStorage := &mocks.MockStorage{} + // mockStorage.On("Exchange").Return("zerox"). + // On("Insert", mock.Anything).Return(nil). + // On("Delete", mock.Anything).Return(nil) + // s := tradelogs.NewManager(zap.S(), []types.Storage{mockStorage}) - p := zxotc2.MustNewParser() + // p := zxotc2.MustNewParser() - mockKafka := &mocks.MockPublisher{} - mockKafka.On("Publish", mock.Anything, mock.Anything).Return(nil) + // mockKafka := &mocks.MockPublisher{} + // mockKafka.On("Publish", mock.Anything, mock.Anything).Return(nil) - h := NewTradeLogHandler(zap.S(), client, s, []parser.Parser{p}, "test", mockKafka) + // h := NewTradeLogHandler(zap.S(), client, s, []parser.Parser{p}, "test", mockKafka) - err = h.ProcessBlock("0x04b65fabd0eaaa00eae00782128a8add39e30098552738c305610259f14ea048", 20181990, 1725436442) - if err != nil { - t.Fatal(err) - } + // err = h.ProcessBlock("0x04b65fabd0eaaa00eae00782128a8add39e30098552738c305610259f14ea048", 20181990, 1725436442) + // if err != nil { + // t.Fatal(err) + // } - assert.True(t, mockStorage.AssertNumberOfCalls(t, "Insert", 1)) - assert.True(t, mockKafka.AssertNumberOfCalls(t, "Publish", 2)) + // assert.True(t, mockStorage.AssertNumberOfCalls(t, "Insert", 1)) + // assert.True(t, mockKafka.AssertNumberOfCalls(t, "Publish", 2)) } func TestAssignLogIndexes(t *testing.T) { diff --git a/v2/pkg/promotionparser/oneinchv2/abi.json b/v2/pkg/promotionparser/oneinchv2/abi.json new file mode 100644 index 0000000..077e05a --- /dev/null +++ b/v2/pkg/promotionparser/oneinchv2/abi.json @@ -0,0 +1,342 @@ +[ + { + "inputs": [ + { + "internalType": "contract IVotable", + "name": "token_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "resolverPercentageThreshold_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceLessThanThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "ETHTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfBounds", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "NotWhitelisted", + "type": "error" + }, + { + "inputs": [], + "name": "OutputArrayTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "PopFromEmptyArray", + "type": "error" + }, + { + "inputs": [], + "name": "SafeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "SamePromotee", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "promoter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "promotee", + "type": "address" + } + ], + "name": "Promotion", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "Registered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "resolverPercentageThreshold", + "type": "uint256" + } + ], + "name": "ResolverPercentageThresholdSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "Unregistered", + "type": "event" + }, + { + "inputs": [], + "name": "BASIS_POINTS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clean", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "getPromotees", + "outputs": [ + { + "internalType": "address[]", + "name": "promotees", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWhitelist", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "promotee", + "type": "address" + } + ], + "name": "promote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "promotions", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "register", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rescueFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resolverPercentageThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resolverPercentageThreshold_", + "type": "uint256" + } + ], + "name": "setResolverPercentageThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IVotable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/v2/pkg/promotionparser/oneinchv2/gen.sh b/v2/pkg/promotionparser/oneinchv2/gen.sh new file mode 100755 index 0000000..68ecbaa --- /dev/null +++ b/v2/pkg/promotionparser/oneinchv2/gen.sh @@ -0,0 +1 @@ +abigen --abi=abi.json --pkg=oneinchv2 --out=oneinchv2.go -type Promotion \ No newline at end of file diff --git a/v2/pkg/promotionparser/oneinchv2/oneinchv2.go b/v2/pkg/promotionparser/oneinchv2/oneinchv2.go new file mode 100644 index 0000000..5c9fb12 --- /dev/null +++ b/v2/pkg/promotionparser/oneinchv2/oneinchv2.go @@ -0,0 +1,1236 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package oneinchv2 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// PromotionMetaData contains all meta data concerning the Promotion contract. +var PromotionMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIVotable\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"resolverPercentageThreshold_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BalanceLessThanThreshold\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ETHTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotWhitelisted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutputArrayTooSmall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PopFromEmptyArray\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SafeTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SamePromotee\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"promoter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"promotee\",\"type\":\"address\"}],\"name\":\"Promotion\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"Registered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"resolverPercentageThreshold\",\"type\":\"uint256\"}],\"name\":\"ResolverPercentageThresholdSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"Unregistered\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASIS_POINTS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clean\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"}],\"name\":\"getPromotees\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"promotees\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWhitelist\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"promotee\",\"type\":\"address\"}],\"name\":\"promote\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"promotions\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"rescueFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolverPercentageThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resolverPercentageThreshold_\",\"type\":\"uint256\"}],\"name\":\"setResolverPercentageThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contractIVotable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// PromotionABI is the input ABI used to generate the binding from. +// Deprecated: Use PromotionMetaData.ABI instead. +var PromotionABI = PromotionMetaData.ABI + +// Promotion is an auto generated Go binding around an Ethereum contract. +type Promotion struct { + PromotionCaller // Read-only binding to the contract + PromotionTransactor // Write-only binding to the contract + PromotionFilterer // Log filterer for contract events +} + +// PromotionCaller is an auto generated read-only Go binding around an Ethereum contract. +type PromotionCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PromotionTransactor is an auto generated write-only Go binding around an Ethereum contract. +type PromotionTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PromotionFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type PromotionFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PromotionSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type PromotionSession struct { + Contract *Promotion // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PromotionCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type PromotionCallerSession struct { + Contract *PromotionCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// PromotionTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type PromotionTransactorSession struct { + Contract *PromotionTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PromotionRaw is an auto generated low-level Go binding around an Ethereum contract. +type PromotionRaw struct { + Contract *Promotion // Generic contract binding to access the raw methods on +} + +// PromotionCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type PromotionCallerRaw struct { + Contract *PromotionCaller // Generic read-only contract binding to access the raw methods on +} + +// PromotionTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type PromotionTransactorRaw struct { + Contract *PromotionTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewPromotion creates a new instance of Promotion, bound to a specific deployed contract. +func NewPromotion(address common.Address, backend bind.ContractBackend) (*Promotion, error) { + contract, err := bindPromotion(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Promotion{PromotionCaller: PromotionCaller{contract: contract}, PromotionTransactor: PromotionTransactor{contract: contract}, PromotionFilterer: PromotionFilterer{contract: contract}}, nil +} + +// NewPromotionCaller creates a new read-only instance of Promotion, bound to a specific deployed contract. +func NewPromotionCaller(address common.Address, caller bind.ContractCaller) (*PromotionCaller, error) { + contract, err := bindPromotion(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PromotionCaller{contract: contract}, nil +} + +// NewPromotionTransactor creates a new write-only instance of Promotion, bound to a specific deployed contract. +func NewPromotionTransactor(address common.Address, transactor bind.ContractTransactor) (*PromotionTransactor, error) { + contract, err := bindPromotion(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PromotionTransactor{contract: contract}, nil +} + +// NewPromotionFilterer creates a new log filterer instance of Promotion, bound to a specific deployed contract. +func NewPromotionFilterer(address common.Address, filterer bind.ContractFilterer) (*PromotionFilterer, error) { + contract, err := bindPromotion(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PromotionFilterer{contract: contract}, nil +} + +// bindPromotion binds a generic wrapper to an already deployed contract. +func bindPromotion(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := PromotionMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Promotion *PromotionRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Promotion.Contract.PromotionCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Promotion *PromotionRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.Contract.PromotionTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Promotion *PromotionRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Promotion.Contract.PromotionTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Promotion *PromotionCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Promotion.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Promotion *PromotionTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Promotion *PromotionTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Promotion.Contract.contract.Transact(opts, method, params...) +} + +// BASISPOINTS is a free data retrieval call binding the contract method 0xe1f1c4a7. +// +// Solidity: function BASIS_POINTS() view returns(uint256) +func (_Promotion *PromotionCaller) BASISPOINTS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "BASIS_POINTS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BASISPOINTS is a free data retrieval call binding the contract method 0xe1f1c4a7. +// +// Solidity: function BASIS_POINTS() view returns(uint256) +func (_Promotion *PromotionSession) BASISPOINTS() (*big.Int, error) { + return _Promotion.Contract.BASISPOINTS(&_Promotion.CallOpts) +} + +// BASISPOINTS is a free data retrieval call binding the contract method 0xe1f1c4a7. +// +// Solidity: function BASIS_POINTS() view returns(uint256) +func (_Promotion *PromotionCallerSession) BASISPOINTS() (*big.Int, error) { + return _Promotion.Contract.BASISPOINTS(&_Promotion.CallOpts) +} + +// GetPromotees is a free data retrieval call binding the contract method 0xe5136e94. +// +// Solidity: function getPromotees(uint256 chainId) view returns(address[] promotees) +func (_Promotion *PromotionCaller) GetPromotees(opts *bind.CallOpts, chainId *big.Int) ([]common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "getPromotees", chainId) + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetPromotees is a free data retrieval call binding the contract method 0xe5136e94. +// +// Solidity: function getPromotees(uint256 chainId) view returns(address[] promotees) +func (_Promotion *PromotionSession) GetPromotees(chainId *big.Int) ([]common.Address, error) { + return _Promotion.Contract.GetPromotees(&_Promotion.CallOpts, chainId) +} + +// GetPromotees is a free data retrieval call binding the contract method 0xe5136e94. +// +// Solidity: function getPromotees(uint256 chainId) view returns(address[] promotees) +func (_Promotion *PromotionCallerSession) GetPromotees(chainId *big.Int) ([]common.Address, error) { + return _Promotion.Contract.GetPromotees(&_Promotion.CallOpts, chainId) +} + +// GetWhitelist is a free data retrieval call binding the contract method 0xd01f63f5. +// +// Solidity: function getWhitelist() view returns(address[]) +func (_Promotion *PromotionCaller) GetWhitelist(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "getWhitelist") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetWhitelist is a free data retrieval call binding the contract method 0xd01f63f5. +// +// Solidity: function getWhitelist() view returns(address[]) +func (_Promotion *PromotionSession) GetWhitelist() ([]common.Address, error) { + return _Promotion.Contract.GetWhitelist(&_Promotion.CallOpts) +} + +// GetWhitelist is a free data retrieval call binding the contract method 0xd01f63f5. +// +// Solidity: function getWhitelist() view returns(address[]) +func (_Promotion *PromotionCallerSession) GetWhitelist() ([]common.Address, error) { + return _Promotion.Contract.GetWhitelist(&_Promotion.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Promotion *PromotionCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Promotion *PromotionSession) Owner() (common.Address, error) { + return _Promotion.Contract.Owner(&_Promotion.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Promotion *PromotionCallerSession) Owner() (common.Address, error) { + return _Promotion.Contract.Owner(&_Promotion.CallOpts) +} + +// Promotions is a free data retrieval call binding the contract method 0x2af05166. +// +// Solidity: function promotions(address , uint256 ) view returns(address) +func (_Promotion *PromotionCaller) Promotions(opts *bind.CallOpts, arg0 common.Address, arg1 *big.Int) (common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "promotions", arg0, arg1) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Promotions is a free data retrieval call binding the contract method 0x2af05166. +// +// Solidity: function promotions(address , uint256 ) view returns(address) +func (_Promotion *PromotionSession) Promotions(arg0 common.Address, arg1 *big.Int) (common.Address, error) { + return _Promotion.Contract.Promotions(&_Promotion.CallOpts, arg0, arg1) +} + +// Promotions is a free data retrieval call binding the contract method 0x2af05166. +// +// Solidity: function promotions(address , uint256 ) view returns(address) +func (_Promotion *PromotionCallerSession) Promotions(arg0 common.Address, arg1 *big.Int) (common.Address, error) { + return _Promotion.Contract.Promotions(&_Promotion.CallOpts, arg0, arg1) +} + +// ResolverPercentageThreshold is a free data retrieval call binding the contract method 0x960462d1. +// +// Solidity: function resolverPercentageThreshold() view returns(uint256) +func (_Promotion *PromotionCaller) ResolverPercentageThreshold(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "resolverPercentageThreshold") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ResolverPercentageThreshold is a free data retrieval call binding the contract method 0x960462d1. +// +// Solidity: function resolverPercentageThreshold() view returns(uint256) +func (_Promotion *PromotionSession) ResolverPercentageThreshold() (*big.Int, error) { + return _Promotion.Contract.ResolverPercentageThreshold(&_Promotion.CallOpts) +} + +// ResolverPercentageThreshold is a free data retrieval call binding the contract method 0x960462d1. +// +// Solidity: function resolverPercentageThreshold() view returns(uint256) +func (_Promotion *PromotionCallerSession) ResolverPercentageThreshold() (*big.Int, error) { + return _Promotion.Contract.ResolverPercentageThreshold(&_Promotion.CallOpts) +} + +// Token is a free data retrieval call binding the contract method 0xfc0c546a. +// +// Solidity: function token() view returns(address) +func (_Promotion *PromotionCaller) Token(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Promotion.contract.Call(opts, &out, "token") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Token is a free data retrieval call binding the contract method 0xfc0c546a. +// +// Solidity: function token() view returns(address) +func (_Promotion *PromotionSession) Token() (common.Address, error) { + return _Promotion.Contract.Token(&_Promotion.CallOpts) +} + +// Token is a free data retrieval call binding the contract method 0xfc0c546a. +// +// Solidity: function token() view returns(address) +func (_Promotion *PromotionCallerSession) Token() (common.Address, error) { + return _Promotion.Contract.Token(&_Promotion.CallOpts) +} + +// Clean is a paid mutator transaction binding the contract method 0xfc4333cd. +// +// Solidity: function clean() returns() +func (_Promotion *PromotionTransactor) Clean(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "clean") +} + +// Clean is a paid mutator transaction binding the contract method 0xfc4333cd. +// +// Solidity: function clean() returns() +func (_Promotion *PromotionSession) Clean() (*types.Transaction, error) { + return _Promotion.Contract.Clean(&_Promotion.TransactOpts) +} + +// Clean is a paid mutator transaction binding the contract method 0xfc4333cd. +// +// Solidity: function clean() returns() +func (_Promotion *PromotionTransactorSession) Clean() (*types.Transaction, error) { + return _Promotion.Contract.Clean(&_Promotion.TransactOpts) +} + +// Promote is a paid mutator transaction binding the contract method 0xf204bdb9. +// +// Solidity: function promote(uint256 chainId, address promotee) returns() +func (_Promotion *PromotionTransactor) Promote(opts *bind.TransactOpts, chainId *big.Int, promotee common.Address) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "promote", chainId, promotee) +} + +// Promote is a paid mutator transaction binding the contract method 0xf204bdb9. +// +// Solidity: function promote(uint256 chainId, address promotee) returns() +func (_Promotion *PromotionSession) Promote(chainId *big.Int, promotee common.Address) (*types.Transaction, error) { + return _Promotion.Contract.Promote(&_Promotion.TransactOpts, chainId, promotee) +} + +// Promote is a paid mutator transaction binding the contract method 0xf204bdb9. +// +// Solidity: function promote(uint256 chainId, address promotee) returns() +func (_Promotion *PromotionTransactorSession) Promote(chainId *big.Int, promotee common.Address) (*types.Transaction, error) { + return _Promotion.Contract.Promote(&_Promotion.TransactOpts, chainId, promotee) +} + +// Register is a paid mutator transaction binding the contract method 0x1aa3a008. +// +// Solidity: function register() returns() +func (_Promotion *PromotionTransactor) Register(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "register") +} + +// Register is a paid mutator transaction binding the contract method 0x1aa3a008. +// +// Solidity: function register() returns() +func (_Promotion *PromotionSession) Register() (*types.Transaction, error) { + return _Promotion.Contract.Register(&_Promotion.TransactOpts) +} + +// Register is a paid mutator transaction binding the contract method 0x1aa3a008. +// +// Solidity: function register() returns() +func (_Promotion *PromotionTransactorSession) Register() (*types.Transaction, error) { + return _Promotion.Contract.Register(&_Promotion.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Promotion *PromotionTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Promotion *PromotionSession) RenounceOwnership() (*types.Transaction, error) { + return _Promotion.Contract.RenounceOwnership(&_Promotion.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Promotion *PromotionTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Promotion.Contract.RenounceOwnership(&_Promotion.TransactOpts) +} + +// RescueFunds is a paid mutator transaction binding the contract method 0x78e3214f. +// +// Solidity: function rescueFunds(address token_, uint256 amount) returns() +func (_Promotion *PromotionTransactor) RescueFunds(opts *bind.TransactOpts, token_ common.Address, amount *big.Int) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "rescueFunds", token_, amount) +} + +// RescueFunds is a paid mutator transaction binding the contract method 0x78e3214f. +// +// Solidity: function rescueFunds(address token_, uint256 amount) returns() +func (_Promotion *PromotionSession) RescueFunds(token_ common.Address, amount *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.RescueFunds(&_Promotion.TransactOpts, token_, amount) +} + +// RescueFunds is a paid mutator transaction binding the contract method 0x78e3214f. +// +// Solidity: function rescueFunds(address token_, uint256 amount) returns() +func (_Promotion *PromotionTransactorSession) RescueFunds(token_ common.Address, amount *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.RescueFunds(&_Promotion.TransactOpts, token_, amount) +} + +// SetResolverPercentageThreshold is a paid mutator transaction binding the contract method 0xcfaa0951. +// +// Solidity: function setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) returns() +func (_Promotion *PromotionTransactor) SetResolverPercentageThreshold(opts *bind.TransactOpts, resolverPercentageThreshold_ *big.Int) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "setResolverPercentageThreshold", resolverPercentageThreshold_) +} + +// SetResolverPercentageThreshold is a paid mutator transaction binding the contract method 0xcfaa0951. +// +// Solidity: function setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) returns() +func (_Promotion *PromotionSession) SetResolverPercentageThreshold(resolverPercentageThreshold_ *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.SetResolverPercentageThreshold(&_Promotion.TransactOpts, resolverPercentageThreshold_) +} + +// SetResolverPercentageThreshold is a paid mutator transaction binding the contract method 0xcfaa0951. +// +// Solidity: function setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) returns() +func (_Promotion *PromotionTransactorSession) SetResolverPercentageThreshold(resolverPercentageThreshold_ *big.Int) (*types.Transaction, error) { + return _Promotion.Contract.SetResolverPercentageThreshold(&_Promotion.TransactOpts, resolverPercentageThreshold_) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Promotion *PromotionTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Promotion.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Promotion *PromotionSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Promotion.Contract.TransferOwnership(&_Promotion.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Promotion *PromotionTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Promotion.Contract.TransferOwnership(&_Promotion.TransactOpts, newOwner) +} + +// PromotionOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Promotion contract. +type PromotionOwnershipTransferredIterator struct { + Event *PromotionOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionOwnershipTransferred represents a OwnershipTransferred event raised by the Promotion contract. +type PromotionOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Promotion *PromotionFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*PromotionOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &PromotionOwnershipTransferredIterator{contract: _Promotion.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Promotion *PromotionFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PromotionOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionOwnershipTransferred) + if err := _Promotion.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_Promotion *PromotionFilterer) ParseOwnershipTransferred(log types.Log) (*PromotionOwnershipTransferred, error) { + event := new(PromotionOwnershipTransferred) + if err := _Promotion.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionPromotionIterator is returned from FilterPromotion and is used to iterate over the raw logs and unpacked data for Promotion events raised by the Promotion contract. +type PromotionPromotionIterator struct { + Event *PromotionPromotion // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionPromotionIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionPromotion) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionPromotion) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionPromotionIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionPromotionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionPromotion represents a Promotion event raised by the Promotion contract. +type PromotionPromotion struct { + Promoter common.Address + ChainId *big.Int + Promotee common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterPromotion is a free log retrieval operation binding the contract event 0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e. +// +// Solidity: event Promotion(address promoter, uint256 chainId, address promotee) +func (_Promotion *PromotionFilterer) FilterPromotion(opts *bind.FilterOpts) (*PromotionPromotionIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "Promotion") + if err != nil { + return nil, err + } + return &PromotionPromotionIterator{contract: _Promotion.contract, event: "Promotion", logs: logs, sub: sub}, nil +} + +// WatchPromotion is a free log subscription operation binding the contract event 0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e. +// +// Solidity: event Promotion(address promoter, uint256 chainId, address promotee) +func (_Promotion *PromotionFilterer) WatchPromotion(opts *bind.WatchOpts, sink chan<- *PromotionPromotion) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "Promotion") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionPromotion) + if err := _Promotion.contract.UnpackLog(event, "Promotion", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParsePromotion is a log parse operation binding the contract event 0xb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e. +// +// Solidity: event Promotion(address promoter, uint256 chainId, address promotee) +func (_Promotion *PromotionFilterer) ParsePromotion(log types.Log) (*PromotionPromotion, error) { + event := new(PromotionPromotion) + if err := _Promotion.contract.UnpackLog(event, "Promotion", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionRegisteredIterator is returned from FilterRegistered and is used to iterate over the raw logs and unpacked data for Registered events raised by the Promotion contract. +type PromotionRegisteredIterator struct { + Event *PromotionRegistered // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionRegisteredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionRegistered represents a Registered event raised by the Promotion contract. +type PromotionRegistered struct { + Addr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRegistered is a free log retrieval operation binding the contract event 0x2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e9. +// +// Solidity: event Registered(address addr) +func (_Promotion *PromotionFilterer) FilterRegistered(opts *bind.FilterOpts) (*PromotionRegisteredIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "Registered") + if err != nil { + return nil, err + } + return &PromotionRegisteredIterator{contract: _Promotion.contract, event: "Registered", logs: logs, sub: sub}, nil +} + +// WatchRegistered is a free log subscription operation binding the contract event 0x2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e9. +// +// Solidity: event Registered(address addr) +func (_Promotion *PromotionFilterer) WatchRegistered(opts *bind.WatchOpts, sink chan<- *PromotionRegistered) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "Registered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionRegistered) + if err := _Promotion.contract.UnpackLog(event, "Registered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRegistered is a log parse operation binding the contract event 0x2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e9. +// +// Solidity: event Registered(address addr) +func (_Promotion *PromotionFilterer) ParseRegistered(log types.Log) (*PromotionRegistered, error) { + event := new(PromotionRegistered) + if err := _Promotion.contract.UnpackLog(event, "Registered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionResolverPercentageThresholdSetIterator is returned from FilterResolverPercentageThresholdSet and is used to iterate over the raw logs and unpacked data for ResolverPercentageThresholdSet events raised by the Promotion contract. +type PromotionResolverPercentageThresholdSetIterator struct { + Event *PromotionResolverPercentageThresholdSet // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionResolverPercentageThresholdSetIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionResolverPercentageThresholdSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionResolverPercentageThresholdSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionResolverPercentageThresholdSetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionResolverPercentageThresholdSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionResolverPercentageThresholdSet represents a ResolverPercentageThresholdSet event raised by the Promotion contract. +type PromotionResolverPercentageThresholdSet struct { + ResolverPercentageThreshold *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterResolverPercentageThresholdSet is a free log retrieval operation binding the contract event 0xcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e. +// +// Solidity: event ResolverPercentageThresholdSet(uint256 resolverPercentageThreshold) +func (_Promotion *PromotionFilterer) FilterResolverPercentageThresholdSet(opts *bind.FilterOpts) (*PromotionResolverPercentageThresholdSetIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "ResolverPercentageThresholdSet") + if err != nil { + return nil, err + } + return &PromotionResolverPercentageThresholdSetIterator{contract: _Promotion.contract, event: "ResolverPercentageThresholdSet", logs: logs, sub: sub}, nil +} + +// WatchResolverPercentageThresholdSet is a free log subscription operation binding the contract event 0xcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e. +// +// Solidity: event ResolverPercentageThresholdSet(uint256 resolverPercentageThreshold) +func (_Promotion *PromotionFilterer) WatchResolverPercentageThresholdSet(opts *bind.WatchOpts, sink chan<- *PromotionResolverPercentageThresholdSet) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "ResolverPercentageThresholdSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionResolverPercentageThresholdSet) + if err := _Promotion.contract.UnpackLog(event, "ResolverPercentageThresholdSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseResolverPercentageThresholdSet is a log parse operation binding the contract event 0xcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e. +// +// Solidity: event ResolverPercentageThresholdSet(uint256 resolverPercentageThreshold) +func (_Promotion *PromotionFilterer) ParseResolverPercentageThresholdSet(log types.Log) (*PromotionResolverPercentageThresholdSet, error) { + event := new(PromotionResolverPercentageThresholdSet) + if err := _Promotion.contract.UnpackLog(event, "ResolverPercentageThresholdSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PromotionUnregisteredIterator is returned from FilterUnregistered and is used to iterate over the raw logs and unpacked data for Unregistered events raised by the Promotion contract. +type PromotionUnregisteredIterator struct { + Event *PromotionUnregistered // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *PromotionUnregisteredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(PromotionUnregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(PromotionUnregistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *PromotionUnregisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PromotionUnregisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PromotionUnregistered represents a Unregistered event raised by the Promotion contract. +type PromotionUnregistered struct { + Addr common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnregistered is a free log retrieval operation binding the contract event 0x75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc. +// +// Solidity: event Unregistered(address addr) +func (_Promotion *PromotionFilterer) FilterUnregistered(opts *bind.FilterOpts) (*PromotionUnregisteredIterator, error) { + + logs, sub, err := _Promotion.contract.FilterLogs(opts, "Unregistered") + if err != nil { + return nil, err + } + return &PromotionUnregisteredIterator{contract: _Promotion.contract, event: "Unregistered", logs: logs, sub: sub}, nil +} + +// WatchUnregistered is a free log subscription operation binding the contract event 0x75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc. +// +// Solidity: event Unregistered(address addr) +func (_Promotion *PromotionFilterer) WatchUnregistered(opts *bind.WatchOpts, sink chan<- *PromotionUnregistered) (event.Subscription, error) { + + logs, sub, err := _Promotion.contract.WatchLogs(opts, "Unregistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(PromotionUnregistered) + if err := _Promotion.contract.UnpackLog(event, "Unregistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUnregistered is a log parse operation binding the contract event 0x75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc. +// +// Solidity: event Unregistered(address addr) +func (_Promotion *PromotionFilterer) ParseUnregistered(log types.Log) (*PromotionUnregistered, error) { + event := new(PromotionUnregistered) + if err := _Promotion.contract.UnpackLog(event, "Unregistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/v2/pkg/promotionparser/oneinchv2/parser.go b/v2/pkg/promotionparser/oneinchv2/parser.go new file mode 100644 index 0000000..8d2111d --- /dev/null +++ b/v2/pkg/promotionparser/oneinchv2/parser.go @@ -0,0 +1,89 @@ +package oneinchv2 + +import ( + "strings" + + "github.com/KyberNetwork/tradelogs/v2/pkg/constant" + "github.com/KyberNetwork/tradelogs/v2/pkg/promotionparser" + storageTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/promotees" + "github.com/KyberNetwork/tradelogs/v2/pkg/types" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + ethereumTypes "github.com/ethereum/go-ethereum/core/types" +) + +const ( + PromotionEvent = "Promotion" +) + +type Parser struct { + abi *abi.ABI + ps *PromotionFilterer + eventHash string +} + +func MustNewParser() *Parser { + ps, err := NewPromotionFilterer(common.Address{}, nil) + if err != nil { + panic(err) + } + ab, err := PromotionMetaData.GetAbi() + if err != nil { + panic(err) + } + promotionEvent, ok := ab.Events[PromotionEvent] + if !ok { + panic("no such event: Promotion") + } + return &Parser{ + ps: ps, + abi: ab, + eventHash: promotionEvent.ID.String(), + } +} + +func (p *Parser) Topics() []string { + return []string{ + p.eventHash, + } +} + +func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storageTypes.Promotee, error) { + if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { + return storageTypes.Promotee{}, promotionparser.ErrInvalidTopic + } + e, err := p.ps.ParsePromotion(log) + if err != nil { + return storageTypes.Promotee{}, err + } + res := storageTypes.Promotee{ + Promoter: strings.ToLower(e.Promoter.String()), + ChainId: e.ChainId.String(), + Promotee: strings.ToLower(e.Promotee.String()), + Timestamp: blockTime * 1000, + TxHash: e.Raw.TxHash.String(), + } + return res, nil +} + +func (p *Parser) Contract() string { + return constant.Promotion1InchV2 +} + +func (p *Parser) UseTraceCall() bool { + return false +} + +func (p *Parser) ParseWithCallFrame(_ types.CallFrame, log ethereumTypes.Log, blockTime uint64) (storageTypes.Promotee, error) { + return p.Parse(log, blockTime) +} + +func (p *Parser) LogFromContract(log ethereumTypes.Log) bool { + return strings.EqualFold(log.Address.String(), constant.AddrPr1InchV2) && + len(log.Topics) > 0 && + strings.EqualFold(log.Topics[0].String(), p.eventHash) +} + +func (p *Parser) Address() string { + return constant.AddrPr1InchV2 +} diff --git a/v2/pkg/promotionparser/parser.go b/v2/pkg/promotionparser/parser.go new file mode 100644 index 0000000..9e75c58 --- /dev/null +++ b/v2/pkg/promotionparser/parser.go @@ -0,0 +1,23 @@ +package promotionparser + +import ( + "errors" + + storageTypes "github.com/KyberNetwork/tradelogs/v2/pkg/storage/promotees" + "github.com/KyberNetwork/tradelogs/v2/pkg/types" + ethereumTypes "github.com/ethereum/go-ethereum/core/types" +) + +var ( + ErrInvalidTopic = errors.New("invalid order topic") +) + +type Parser interface { + Parse(log ethereumTypes.Log, blockTime uint64) (storageTypes.Promotee, error) + Topics() []string + Contract() string + UseTraceCall() bool + ParseWithCallFrame(callFrame types.CallFrame, log ethereumTypes.Log, blockTime uint64) (storageTypes.Promotee, error) + LogFromContract(log ethereumTypes.Log) bool + Address() string +} diff --git a/v2/pkg/storage/promotees/storage.go b/v2/pkg/storage/promotees/storage.go new file mode 100644 index 0000000..a288348 --- /dev/null +++ b/v2/pkg/storage/promotees/storage.go @@ -0,0 +1,148 @@ +package promotees + +import ( + "fmt" + "reflect" + "strings" + + "github.com/KyberNetwork/tradelogs/v2/pkg/constant" + "github.com/Masterminds/squirrel" + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +const ( + promoteesTable = "promotees" + nameTable = "promoteesName" +) + +type Storage struct { + db *sqlx.DB + l *zap.SugaredLogger +} + +func New(l *zap.SugaredLogger, db *sqlx.DB) *Storage { + return &Storage{ + db: db, + l: l, + } +} + +func (s *Storage) Contract() string { + return constant.Promotion1InchV2 +} + +func (s *Storage) Insert(promotees []Promotee) error { + if len(promotees) == 0 { + return nil + } + + b := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Insert(promoteesTable).Columns( + promoteesColumns()..., + ) + for _, promotee := range promotees { + b = b.Values( + promotee.SerializePromotees()..., + ) + } + q, p, err := b.Suffix("ON CONFLICT (promotee, promoter, chain_id) DO NOTHING").ToSql() + if err != nil { + s.l.Errorw("Error build insert", "error", err) + return err + } + if _, err := s.db.Exec(q, p...); err != nil { + s.l.Errorw("Error exec insert", "sql", q, "arg", p, "error", err) + return err + } + return nil +} + +func (s *Storage) Get(query PromoteesQuery) ([]Promotee, error) { + builder := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). + Select(fmt.Sprintf("%s.promoter, promotee, chain_id, tx_hash, timestamp, name", promoteesTable)). + From(promoteesTable). + Join(fmt.Sprintf("%s ON %s.promoter = %s.promoter", nameTable, promoteesTable, nameTable)) + + v := reflect.ValueOf(query) + types := v.Type() + for i := 0; i < v.NumField(); i++ { + tag := string(types.Field(i).Tag.Get("form")) + if v.Field(i).IsZero() { + continue + } + builder = builder.Where(squirrel.Eq{tag: strings.ToLower(v.Field(i).String())}) + } + + q, p, err := builder.OrderBy(fmt.Sprintf("%s.timestamp DESC", promoteesTable)).ToSql() + if err != nil { + return nil, err + } + + var promotees []Promotee + if err := s.db.Select(&promotees, q, p...); err != nil { + return nil, err + } + + return promotees, nil +} + +func (s *Storage) Delete(blocks []uint64) error { + if len(blocks) == 0 { + return nil + } + q, p, err := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). + Delete(promoteesTable).Where(squirrel.Eq{"block_number": blocks}). + ToSql() + if err != nil { + s.l.Errorw("Error while delete", "block_number", blocks, "error", err) + return err + } + if _, err := s.db.Exec(q, p...); err != nil { + return err + } + return nil +} + +func (s *Storage) InsertPromoterName(promotees []Promotee) error { + if len(promotees) == 0 { + return nil + } + + b := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Insert(nameTable).Columns( + nameColumns()..., + ) + for _, promotee := range promotees { + b = b.Values( + promotee.SerializeNames()..., + ) + } + q, p, err := b.Suffix(`ON CONFLICT (promoter) DO UPDATE SET name=excluded.name`).ToSql() + + if err != nil { + s.l.Errorw("Error build insert", "error", err) + return err + } + if _, err := s.db.Exec(q, p...); err != nil { + s.l.Errorw("Error exec insert", "sql", q, "arg", p, "error", err) + return err + } + return nil +} + +func promoteesColumns() []string { + return []string{ + "promoter", + "promotee", + "timestamp", + "tx_hash", + "chain_id", + "block_number", + } +} + +func nameColumns() []string { + return []string{ + "promoter", + "name", + } +} diff --git a/v2/pkg/storage/promotees/types.go b/v2/pkg/storage/promotees/types.go new file mode 100644 index 0000000..3fafd59 --- /dev/null +++ b/v2/pkg/storage/promotees/types.go @@ -0,0 +1,40 @@ +package promotees + +import ( + "strings" +) + +type Promotee struct { + Promoter string `db:"promoter" json:"promoter,omitempty"` + Promotee string `db:"promotee" json:"promotee,omitempty"` + Timestamp uint64 `db:"timestamp" json:"timestamp,omitempty"` + TxHash string `db:"tx_hash" json:"tx_hash,omitempty"` + ChainId string `db:"chain_id" json:"chain_id,omitempty"` + BlockNumber uint64 `db:"block_number" json:"block_number,omitempty"` + Name string `db:"name" json:"name,omitempty"` +} + +type PromoteesQuery struct { + Promoter string `form:"promoter" json:"promoter,omitempty"` + Promotee string `form:"promotee" json:"promotee,omitempty"` + ChainId string `form:"chain_id" json:"chain_id,omitempty"` + Name string `form:"name" json:"name,omitempty"` +} + +func (o *Promotee) SerializePromotees() []interface{} { + return []interface{}{ + strings.ToLower(o.Promoter), + strings.ToLower(o.Promotee), + o.Timestamp, + o.TxHash, + o.ChainId, + o.BlockNumber, + } +} + +func (o *Promotee) SerializeNames() []interface{} { + return []interface{}{ + strings.ToLower(o.Promoter), + o.Name, + } +}