From 30bafa0185b6db212fcd92908d1ee111afbb065d Mon Sep 17 00:00:00 2001 From: Hugo Trentesaux <hugo@trentesaux.fr> Date: Tue, 22 Nov 2022 09:56:21 +0100 Subject: [PATCH] feat: batch transfer --- README.md | 4 ++++ res/metadata.scale | Bin 128198 -> 127211 bytes src/commands/transfer.rs | 33 +++++++++++++++++++++++++++++++++ src/main.rs | 30 +++++++++++++++++++++++++----- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 640f0fd..a23d0ff 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ CLI client for [Duniter-V2S](https://git.duniter.org/nodes/rust/duniter-v2s/). +Using +- https://github.com/duniter/substrate +- https://github.com/duniter/subxt + ## Usage If using a different runtime, update the metadata for the client to compile: diff --git a/res/metadata.scale b/res/metadata.scale index 3ec2c111f3089edbf7b193d08cddc0ea353bec76..d7c41820b07a0a2e6198009041d239e70602a2d9 100644 GIT binary patch delta 2014 zcmc&#X-rgC6u#e^%K*wUxQ@6DwN_9JYN4V<D*`RVA{ubP4PR#-@RXT>HxG0Y7f@VN zeh{jsm{{e9CYox4Et%SCE2;KJ6C3{+SKKvfW2M%lX<D0}H$$Vf{o6EoFZbMY?pg15 z&i(d5^ba?q?Ox4P6V5c*yX?rQpbZ`jp~vqbqd%l@!r@U(6_n=2+lZoCH`D>~5~)QV zGgxY>W_>^i$hL~>!{~Q6=1z%{(pge#>VBV;Wr&rCam@AmG$Dke)bG`#h?T4$!i$U% z4iQi5JSZKM#B61-6#NMp<A|4Hm~8uGN-{n3Aa;C>nP+IK={M&3&D@$A{~FCx<`1(p zD-c%M-*<q%(l9hd_h>#-H+3yA&ywfXu(l_d=l50WhF9|l&?pU)piqgm*r-uMCM0!f zDBvW2vzT^DuS5o-X;~%jVyLAOuOpVaD=`NB=x!y(p+Ch}VItz_%_^3~lfMeHkwC|) zFd2z-rwVCwq!y!X4*4OStALZP)gpSf>hTy_Ah7IjsYD_R=aMAXvB;%H(sY@AmpdYL z^<@>LIu%X~poBWOW~_YC&O)_D=lhBjWuR<)$xuU|__?L{YK+1lO0Px^29s_rL+D^N zreP@EsKy%{^iUmBF^o!dyozKpbu?on{i<V*k|Nu>dy;A8DkLD4R#f2rfSe*<*hw)% zDxZNPY}B-hD<<hn15>!RKN@V?PN@OjMbpv%mx^l}Kt9*@#A>{+jFoLSbB55$8W>8N zMUSS9CgR}S?Zwo*>^#jdpJ&X_tF<_KrS4WO(7Am4tM!Z&J@CyTEx#xbsJF1<FIIg) z>!eU<ju(sh&L`C)jpO>>i|Mu~`IP2*kwWP{>{KTH7kN$oUvlZ6749b?#WdMA>(=m4 zbpvh#Gw9v5I2xC03FFQx!YK+u_8<<+*dnVBi=`;0#0?lh=hyRf&9~@taSOtx%B543 zOPaI<8H1NgS;`iKD&btHxpT^93bC9rHllTqYS~#X1$R96v(8F-pOUvvsqO_OFF6~r zA-2v^@=8%3+SiC(3WAii8DC&M^=`%vr72>74mV?fvPHJ}%SX}GW;n2e9yMdU(jsZu z1O{w_frQXoTd)aerH<{4>kC^^lCn#3q^UfJm=My{F89g~c|abLo${pYmZF`K_AtQJ zZQSmABlO4HFaaGA`pGtoqt<O0PMO>B3SF?My6t$a-w}zp0z(zzNQj+vI+RY?ma*GO zHSHK~@3Nd8r<QiO&_zd?h2s%>ciNGTlNLQ)>6X-*j}ak#4>FUL#Y$-3XZU=KGAo<P zFCyC}TE>MwxX8l@Q|R<1q;eZQx&)U!ijxt724BWl<(Z9gF5?)I=<#J%Ikf{c{tEVo ziL+Nw!W}&FD#ml`7GA|^n@BF9#2$ETjbx{W9;{&OpYP$BHkO|C;JAHOHrHqvox8#q zxOj~*;Gu-uD71;pk7)UIjy#QaUT3!)V&`>Mvqd5b2P6nLkQMQ?iH_eu-oLn;NM~;H z&<wjfNc(PK;6HsPzT|T<ZN1H|vqGQVMxKIc^vhk0wPnc}H2NMp%ndELhouS%sPjJ7 zpor2Q@Ng@l!UwoKdcK@FXrAF;8$@J@8DZ`CfdFKbSU|ZCaROTCkB8`%sHanpQO@v7 z?nNcTuc?<Y(L~33u?Sm2{eHsNz!v)M2^L~UDCK8FVR(zoZI#khm{+a2SM!UvL^J%Q zn$M#d?Uefz1C71XksTJ6tzD=Y0iIPI(lIH_c}MeU0X=X)x*{iv{f5bt+6*3&uGGH_ ty0uQ(m>%9O()6lo^Q3HCnOChERa%*$`U0xknt$`upqHP%ZrRu+{{(`pY`6db delta 2671 zcmeHJZERF!7Ji>Q@06hwoKi{(6ugKa)smJkwWgqBTck1Nqb*n@Sa0urr@b<BZ<)CR z6hCOCMp5`toAv;S$?`+8=$33XFtS;qBw|n@F}nywz62Ln7yS6K{&Uwo_YM%V@t^UZ z$t3Tc^PclO&pG#f&$-twkNV*2QF%$_8RJg&<Q>dIMQhR0P9u>}UaOUHY)_?HH@O~d zSdU_q)3^?NHDhzV<#pAhl;PQ~vqGh8*IMR!jVj%#Oix)NBzMtCg-Kf-*V9us%`dS} zo#STOI~tX#?2XE*Q7JFo>;_26#}rbYVlQ0<ZXBBP(@l1?<F*+PrghKNO`l!qwxt}; z_PSacjLmgP+hg_sv{4ymhkDc!VY!31bSIN+Qz_kz>ni6JK&F|&_p>}EjU^K9CS|dl z4#Q~=<isqC)u%<C+_j7@Stu^M$)_8+t(Kn$Hman%F_*_ETCSjPT~VJ-XH=@jaQxhv z*%v1w@{^ohHw{O3{Cs&UP^7mh)5xSbF;BPC!QMtAVOyN5)$9j1yQ>`2b>em^sjQ%6 zqvanNKXA2uwj2(ZDB~==<$0@6m3|D1S>k3KOXSPW8%o^N&1$FUa~GR6NLtW}C1b); zlpx9ij4-{x28^Z?tuP7;C1(3rO`hRp(n5r3@ssG7H(JV)<(>Yykg^$LB_h#fuA_ty z(Iz*kq!=rOfCv^D5m8Y{BTu5KsF=;#Bq{hOWF%TB#Z+2s;Lehk6+TNW!Eegys=1lD z5cIx*N`QXw7ma4MVF5z4wheWxd~X{Y!}PZ{R3MKulmCsP`6lKgLhUAIa1yVWxC{C8 zwuw0yLzn%%0xGufFve1gg}E3<FIy<1KPgPZZS=81HKG)W^HNB4aa3VEZH?nz6w#qL z?!yH7HjX<{OhxVJ#dO-$jz_hbvj6CX$@Eh@#ub%T*E_+xY~Z_A%k|_O`W)5*Dz`C@ zb7-|u6$;5tGHgaYU}Gw$a>8aUVfwF)T2AGJiybWLlc%s<n<M)#SKm%s)}w&gUtEv- zCe#LRlh3f*U^rdDVFMw77Dj(OfikX8Zvqc6?7ImJO`IzWe!uF!U-gB*#VOUQe(mub zvnc2VLW-E|f9T4TY+njr0Ckk{aG;>x-z+$(i4xI}t;paFnZMHSA*-ZVCHo5=nND&G z=4)#tl>>Ls+ASC=SQh{qvP2k?Dj!Ehv68ZhafB^VvRawd&5MOl)bcd?CfGh2H>_k3 zw1I;*+z86t2<rM-P=;d9;JMLVeo#h=XS2tj!GMMydSWa7f){8~H{aOpIRN^5H^yr_ zWxu;-8ijihMITM<!QB|h#(J<H*iF}-hjsgFl9kQo*2xb->U-tua=#ps!}72^CO?$) z(>9dS%iB;%5BFjUeYy?zU_Wv9iDAfJCeylJ+=1cT^PXPJ%0DPkP?zG?b1?f+FNUMq zVcB0XSV98>n38wI=Q~P=2B1$pA|sXUmfF~w%J6_qs?x^X%4*mp03SPuavaM&HxEMB zSW;gtO0%yHV!>o>n#dmiGv1kzm(L+`2fcTSyVRaj&_l<C$R0Vxt(gtqe2Ur72G2u} zXg)Un6Qb(VnCZ_S^EBS#hC1;K?hkPpXyqCFA#a|KRz?>ta_&VV+}Nj5?FiRyI=Lfw zKlD{d(7k72h5ijeubsscm`OjL<yK!t(=K8kee@ZMwA%z-`V4Eh{a2mC(jex!OPtIc z8a~I=69kQ%;}Bog%n;^Enspuva}3YZ#q+571)7EQuM0dw0-D3O7$X12P(^S0M2oT` zmr$c2Mx|GnVv($)+AB;^pWSi=Yc({`>3?7oR?@PoJbhMD@+w#_E&Y;5!a9n7iN7M5 zo$*f`m3Wq}UgK1H=)voV^FiBpoolk4&RoZ1*qN>P2JZqp>AP>S8hzO%-ysY+AY;2} z`S+L@-z&Qxs_9VX`X>HzTdh)Qp4+d>=>37MdGig+ei^L{ERQHhrS0^P)N>vUZp!1Y m6R&Gn>azn6p7o|WEW68te~&4<y~8_3AAgT2;SXi^5&1vxv|bkg diff --git a/src/commands/transfer.rs b/src/commands/transfer.rs index 65c3b85..82ea9e1 100644 --- a/src/commands/transfer.rs +++ b/src/commands/transfer.rs @@ -4,6 +4,9 @@ use anyhow::Result; use sp_core::{crypto::AccountId32, sr25519::Pair}; use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner}; +type Call = gdev::runtime_types::gdev_runtime::Call; +type BalancesCall = gdev::runtime_types::pallet_balances::pallet::Call; + pub async fn transfer( pair: Pair, client: Client, @@ -35,3 +38,33 @@ pub async fn transfer( Ok(()) } + +pub async fn transfer_multiple( + pair: Pair, + client: Client, + amount: u64, + dests: Vec<AccountId32>, +) -> Result<()> { + // build the list of transactions from the destination accounts + let transactions: Vec<Call> = dests + .into_iter() + .map(|dest| { + Call::Balances(BalancesCall::transfer_keep_alive { + dest: dest.into(), + value: amount, + }) + }) + .collect(); + + // wrap these calls in a batch call + client + .tx() + .sign_and_submit_then_watch( + &gdev::tx().utility().batch(transactions), + &PairSigner::new(pair.clone()), + BaseExtrinsicParamsBuilder::new(), + ) + .await?; + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index ac32f55..c8e3cc9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -127,11 +127,22 @@ pub enum Subcommand { new_key: sp_core::crypto::AccountId32, }, Transfer { - balance: u64, + /// Amount to transfer + amount: u64, + /// Destination address dest: sp_core::crypto::AccountId32, - #[clap(short = 'k')] + /// Prevent from going below account existential deposit + #[clap(short = 'k', long = "keep-alive")] keep_alive: bool, }, + /// Transfer the same amount for each space-separated address. + /// If an address appears mutiple times, it will get multiple times the same amount + TransferMultiple { + /// Amount given to each destination address + amount: u64, + /// List of target addresses + dests: Vec<sp_core::crypto::AccountId32>, + }, /// Rotate and set session keys UpdateKeys, } @@ -174,7 +185,7 @@ async fn main() -> Result<()> { println!("Account address: {}", account_id); } - let client = Client::new().await.unwrap(); + let client = Client::new().await?; if let Some(account_id) = &account_id { let account = client @@ -272,19 +283,28 @@ async fn main() -> Result<()> { .await? } Subcommand::Transfer { - balance, + amount, dest, keep_alive, } => { commands::transfer::transfer( pair.expect("This subcommand needs a secret."), client, - balance, + amount, dest, keep_alive, ) .await? } + Subcommand::TransferMultiple { amount, dests } => { + commands::transfer::transfer_multiple( + pair.expect("This subcommand needs a secret."), + client, + amount, + dests, + ) + .await? + } Subcommand::UpdateKeys => commands::smith::update_session_keys( pair.expect("This subcommand needs a secret."), client, -- GitLab