大家好,我开发了一个扫块的 工具包,可以用来方便的监听 交易动态 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Joker123456789
V2EX    以太坊

大家好,我开发了一个扫块的 工具包,可以用来方便的监听 交易动态

  •  
  • &bsp; Joker123456789 2022-11-05 17:49:06 +08:00 2378 次点击
    这是一个创建于 1083 天前的主题,其中的信息可能已经有所发展或是发生改变。

    开发语言是 java ,底层依赖了 Web3J , 废话不多说,直接上示例

    引入依赖

    <dependency> <groupId>com.github.yuyenews</groupId> <artifactId>Magician-web3</artifactId> <version>1.0.0</version> </dependency> <!-- This is the logging package, you must have it or the console will not see anything, any logging package that can bridge with slf4j is supported --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.7.12</version> </dependency> 

    创建监听器

    监听器 可以创建多个,根据你的需求 分别设置监听条件

    /** * 创建一个类,实现 EthMonitorEvent 接口 即可 */ public class EventDemo implements EthMonitorEvent { /** * 筛选条件,如果遇到了符合条件的交易,会自动触发 call 方法 * 这些条件都是 并且的关系,必须要同时满足才行 * 如果不想根据某个条件筛选,直接不给那个条件设置值就好了 * 这个方法如果不实现,或者返回 null , 那么就代表监听任意交易 */ @Override public EthMonitorFilter ethMonitorFilter() { return EthMonitorFilter.builder() .setFromAddress("0x131231249813d334C58f2757037F68E2963C4crc") // 筛选 fromAddress 发送的交易 .setToAddress("0x552115849813d334C58f2757037F68E2963C4c5e") // 筛选 toAddress 或 合约地址 收到的交易 .setMinValue(BigInteger.valueOf(1)) // 筛选发送的主链币数量 >= minValue 的交易 .setMaxValue(BigInteger.valueOf(10)) // 筛选发送的主链币数量 <= maxValue 的交易 .setFunctionCode("0xasdas123"); // 筛选调用合约内 某方法 的交易 } /** * 如果遇到了符合上面条件的交易,就会触发这个方法 * transactionModel.getEthTransactionModel() 是一个交易对象,内部包含 hash ,value ,from ,to 等 所有的数据 */ @Override public void call(TransactionModel transactionModel) { String template = "EventOne 扫描到了, hash:{0}, from:{1}, to: {2}, input: {3}"; template = template.replace("{0}", transactionModel.getEthTransactionModel().getBlockHash()); template = template.replace("{1}", transactionModel.getEthTransactionModel().getFrom()); template = template.replace("{2}", transactionModel.getEthTransactionModel().getTo()); template = template.replace("{3}", transactionModel.getEthTransactionModel().getInput()); System.out.println(template); } } 

    开启一个扫块任务

     // 初始化线程池,核心线程数必须 >= 扫块的任务数量,建议等于扫块的任务数量 EventThreadPool.init(1); // 开启一个扫块任务,如果你想扫描多个链,那么直接拷贝这段代码,并修改配置即可 MagicianBlockchainScan.create() .setRpcUrl("https://data-seed-prebsc-1-s1.binance.org:8545/") // 节点的 RPC 地址 .setChainType(ChainType.ETH) // 要扫描的链(如果设置成 ETH ,那么可以扫描 BSC, POLYGAN 等其他任意 以太坊标准的链) .setScanPeriod(5000) // 每轮扫描的间隔 .setScanSize(1000) // 每轮扫描的块数 .setBeginBlockNumber(BigInteger.valueOf(24318610)) // 从哪个块高开始扫描 .addEthMonitorEvent(new EventOne()) // 添加 监听事件 .addEthMonitorEvent(new EventTwo()) // 添加 监听事件 .addEthMonitorEvent(new EventThree()) // 添加 监听事件 .start(); // TODO 暂时不支持 SOL 和 TRON , 正在开发中...... 

    Web3J 扩展

    在 Web3j 的基础上进行了二次封装,扩展了几个基础的方法,可以在一定程度上减轻开发者的工作量

    主链币查询以及转账

    String privateKey = ""; // 私钥 Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-1-s1.binance.org:8545/")); // 链的 RPC 地址 EthHelper ethHelper = MagicianWeb3.getEthBuilder().getEth(web3j, privateKey); // 余额查询 BigInteger balance = ethHelper.balanceOf(fromAddress); // 转账 TransactionReceipt transactiOnReceipt= ethHelper.transfer( toAddress, BigDecimal.valueOf(1), Convert.Unit.ETHER ); 

    InputData 编解码

    EthAbiCodec ethAbiCodec = MagicianWeb3.getEthBuilder().getEthAbiCodec(); // 编码 String inputData = ethAbiCodec.getInputData( "transfer", // 方法名 new Address(toAddress), // 参数 1 new Uint256(new BigInteger("1000000000000000000")) // 参数 2 ,如果还有其他参数,可以继续传入下一个 ); // 解码 List<Type> result = ethAbiCodec.decoderInputData( "0x" + inputData.substring(10), // 去除方法签名的 inputData new TypeReference<Address>() {}, // 被编码的方法的参数 1 类型 new TypeReference<Uint256>() {} // 被编码的方法的参数 2 类型, 如果还有其他参数,可以继续传入下一个 ); for(Type type : result){ System.out.println(type.getValue()); } // 获取方法签名,其实就是 inputData 的前十位 String functiOnCode= ethAbiCodec.getFunAbiCode( "transfer", // 方法名 new Address(toAddress), // 参数 1 ,值随意传,反正我们要的方法签名,不是完整的 inputData new Uint256(new BigInteger("1000000000000000000")) // 参数 2 ,值随意传,反正我们要的方法签名,不是完整的 inputData ,如果还有其他参数,可以继续传入下一个 ); 

    合约查询 以及 写入

    String privateKey = ""; // 私钥 Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-1-s1.binance.org:8545/")); // 链的 RPC 地址 EthContract ethCOntract= MagicianWeb3.getEthBuilder().getEthContract(web3j, fromAddressPrivateKey); EthAbiCodec ethAbiCodec = MagicianWeb3.getEthBuilder().getEthAbiCodec(); // 查询 List<Type> result = ethContract.select( contractAddress, // 合约地址 ethAbiCodec.getInputData( "balanceOf", // 要调用的方法名称 new Address(toAddress) // 方法的参数,如果有多个,可以继续传入下一个参数 ), // 要调用的方法的 inputData new TypeReference<Uint256>() {} // 方法的返回类型,如果有多个返回值,可以继续传入下一个参数 ); // 往合约里写入数据 // gasPrice ,gasLimit 两个参数,如果想用默认值可以不传,或者传 null // 如果不传的话,两个参数都必须不传,要传就一起传, 如果设置为 null 的话,可以一个为 null ,一个有值 SendResultModel sendResultModel = ethContract.sendRawTransaction( fromAddress, // 调用者的地址 contractAddress, // 合约地址 new BigInteger("1200000"), // gasPrice ,如果想用默认值 可以直接传 null ,或者不传这个参数 new BigInteger("800000"), // gasLimit ,如果想用默认值 可以直接传 null ,或者不传这个参数 ethAbiCodec.getInputData( "transfer", // 要调用的方法名称 new Address(toAddress), // 方法的参数,如果有多个,可以继续传入下一个参数 new Uint256(new BigInteger("1000000000000000000")) // 方法的参数,如果有多个,可以继续传入下一个参数 ) // 要调用的方法的 inputData ); sendResultModel.getEthSendTransaction(); // 发送交易后的结果 sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果 

    github 地址:https://github.com/Magician-blockchain/Magician-web3

    第 1 条附言    2022-11-06 16:03:10 +08:00
    为了更形象的解释这个工具包,我举个例子,比如:

    我如果就是只想 在某个地址 收到了主链币时,程序可以收到这条交易信息的所有字段。 用我这个工具包来做的话,真正需要手写的代码 只有半行而已(不包括 收到通知后的业务操作,因为这个是逃不掉的,用什么工具开发 都得写)。

    如果 在上面那个场景下 再加一个场景,当某个地址 收到或者发送的主链币数量在某个区间时,程序也能收到对应的交易信息,那么什么都不用改,只需要再写 半行代码而已。 而且这半行 跟 那半行 是 隔离的,完全的解耦。

    如果 这两个场景,你需要下掉一个,那只需要直接删 或者注释即可。

    如果还有第三个场景,那就再写半行,最多一行。

    注:我上面说的半行,一行,指的是需要手写的代码,不是总代码,但是总代码也不多,每个场景对应一个实现类,里面实现两个方法而已。

    作为开发者,只需要关注 自己需要监听什么样的事件,其他的都不需要去耗费精力。 对于写入合约的交易,可能需要开发者 自己进行一次二筛,比如去查 log 来判定 本次交易是否有效,解析 inputData 来获取 更详细的信息,进行判断等。
    2条回复    2022-11-05 18:19:25 +08:00
    14v45mJPBYJW8dT7
        1
    14v45mJPBYJW8dT7  
       2022-11-05 17:53:26 +08:00
    token 交易要监听 log ,只关注 data 会出现 revert 或者恶意消息这种情况
    Joker123456789
        2
    Joker123456789  
    OP
       2022-11-05 18:19:25 +08:00
    @rimutuyuan 是的,所以需要二筛, 合约千变万化,光是 ERCXX 这种标准合约就很多了,再加上其他的一些 dapp ,所以没办法统一处理,只能交给开发者自己二筛了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1050 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 18:03 PVG 02:03 LAX 11:03 JFK 14:03
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86