| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922 | 
							- const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !== 'undefined' ? window: typeof global !== 'undefined' ? global: typeof self !== 'undefined' ? self: {});
 
- (function (global, factory) {
 
-     typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
 
-     typeof define === 'function' && define.amd ? define(['exports'], factory) :
 
-     (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ethers = {}));
 
- })(this, (function (exports) { 'use strict';
 
-     /* Do NOT modify this file; see /src.ts/_admin/update-version.ts */
 
-     /**
 
-      *  The current version of Ethers.
 
-      */
 
-     const version = "6.13.5";
 
-     /**
 
-      *  Property helper functions.
 
-      *
 
-      *  @_subsection api/utils:Properties  [about-properties]
 
-      */
 
-     function checkType(value, type, name) {
 
-         const types = type.split("|").map(t => t.trim());
 
-         for (let i = 0; i < types.length; i++) {
 
-             switch (type) {
 
-                 case "any":
 
-                     return;
 
-                 case "bigint":
 
-                 case "boolean":
 
-                 case "number":
 
-                 case "string":
 
-                     if (typeof (value) === type) {
 
-                         return;
 
-                     }
 
-             }
 
-         }
 
-         const error = new Error(`invalid value for type ${type}`);
 
-         error.code = "INVALID_ARGUMENT";
 
-         error.argument = `value.${name}`;
 
-         error.value = value;
 
-         throw error;
 
-     }
 
-     /**
 
-      *  Resolves to a new object that is a copy of %%value%%, but with all
 
-      *  values resolved.
 
-      */
 
-     async function resolveProperties(value) {
 
-         const keys = Object.keys(value);
 
-         const results = await Promise.all(keys.map((k) => Promise.resolve(value[k])));
 
-         return results.reduce((accum, v, index) => {
 
-             accum[keys[index]] = v;
 
-             return accum;
 
-         }, {});
 
-     }
 
-     /**
 
-      *  Assigns the %%values%% to %%target%% as read-only values.
 
-      *
 
-      *  It %%types%% is specified, the values are checked.
 
-      */
 
-     function defineProperties(target, values, types) {
 
-         for (let key in values) {
 
-             let value = values[key];
 
-             const type = (types ? types[key] : null);
 
-             if (type) {
 
-                 checkType(value, type, key);
 
-             }
 
-             Object.defineProperty(target, key, { enumerable: true, value, writable: false });
 
-         }
 
-     }
 
-     /**
 
-      *  All errors in ethers include properties to ensure they are both
 
-      *  human-readable (i.e. ``.message``) and machine-readable (i.e. ``.code``).
 
-      *
 
-      *  The [[isError]] function can be used to check the error ``code`` and
 
-      *  provide a type guard for the properties present on that error interface.
 
-      *
 
-      *  @_section: api/utils/errors:Errors  [about-errors]
 
-      */
 
-     function stringify$1(value) {
 
-         if (value == null) {
 
-             return "null";
 
-         }
 
-         if (Array.isArray(value)) {
 
-             return "[ " + (value.map(stringify$1)).join(", ") + " ]";
 
-         }
 
-         if (value instanceof Uint8Array) {
 
-             const HEX = "0123456789abcdef";
 
-             let result = "0x";
 
-             for (let i = 0; i < value.length; i++) {
 
-                 result += HEX[value[i] >> 4];
 
-                 result += HEX[value[i] & 0xf];
 
-             }
 
-             return result;
 
-         }
 
-         if (typeof (value) === "object" && typeof (value.toJSON) === "function") {
 
-             return stringify$1(value.toJSON());
 
-         }
 
-         switch (typeof (value)) {
 
-             case "boolean":
 
-             case "symbol":
 
-                 return value.toString();
 
-             case "bigint":
 
-                 return BigInt(value).toString();
 
-             case "number":
 
-                 return (value).toString();
 
-             case "string":
 
-                 return JSON.stringify(value);
 
-             case "object": {
 
-                 const keys = Object.keys(value);
 
-                 keys.sort();
 
-                 return "{ " + keys.map((k) => `${stringify$1(k)}: ${stringify$1(value[k])}`).join(", ") + " }";
 
-             }
 
-         }
 
-         return `[ COULD NOT SERIALIZE ]`;
 
-     }
 
-     /**
 
-      *  Returns true if the %%error%% matches an error thrown by ethers
 
-      *  that matches the error %%code%%.
 
-      *
 
-      *  In TypeScript environments, this can be used to check that %%error%%
 
-      *  matches an EthersError type, which means the expected properties will
 
-      *  be set.
 
-      *
 
-      *  @See [ErrorCodes](api:ErrorCode)
 
-      *  @example
 
-      *    try {
 
-      *      // code....
 
-      *    } catch (e) {
 
-      *      if (isError(e, "CALL_EXCEPTION")) {
 
-      *          // The Type Guard has validated this object
 
-      *          console.log(e.data);
 
-      *      }
 
-      *    }
 
-      */
 
-     function isError(error, code) {
 
-         return (error && error.code === code);
 
-     }
 
-     /**
 
-      *  Returns true if %%error%% is a [[CallExceptionError].
 
-      */
 
-     function isCallException(error) {
 
-         return isError(error, "CALL_EXCEPTION");
 
-     }
 
-     /**
 
-      *  Returns a new Error configured to the format ethers emits errors, with
 
-      *  the %%message%%, [[api:ErrorCode]] %%code%% and additional properties
 
-      *  for the corresponding EthersError.
 
-      *
 
-      *  Each error in ethers includes the version of ethers, a
 
-      *  machine-readable [[ErrorCode]], and depending on %%code%%, additional
 
-      *  required properties. The error message will also include the %%message%%,
 
-      *  ethers version, %%code%% and all additional properties, serialized.
 
-      */
 
-     function makeError(message, code, info) {
 
-         let shortMessage = message;
 
-         {
 
-             const details = [];
 
-             if (info) {
 
-                 if ("message" in info || "code" in info || "name" in info) {
 
-                     throw new Error(`value will overwrite populated values: ${stringify$1(info)}`);
 
-                 }
 
-                 for (const key in info) {
 
-                     if (key === "shortMessage") {
 
-                         continue;
 
-                     }
 
-                     const value = (info[key]);
 
-                     //                try {
 
-                     details.push(key + "=" + stringify$1(value));
 
-                     //                } catch (error: any) {
 
-                     //                console.log("MMM", error.message);
 
-                     //                    details.push(key + "=[could not serialize object]");
 
-                     //                }
 
-                 }
 
-             }
 
-             details.push(`code=${code}`);
 
-             details.push(`version=${version}`);
 
-             if (details.length) {
 
-                 message += " (" + details.join(", ") + ")";
 
-             }
 
-         }
 
-         let error;
 
-         switch (code) {
 
-             case "INVALID_ARGUMENT":
 
-                 error = new TypeError(message);
 
-                 break;
 
-             case "NUMERIC_FAULT":
 
-             case "BUFFER_OVERRUN":
 
-                 error = new RangeError(message);
 
-                 break;
 
-             default:
 
-                 error = new Error(message);
 
-         }
 
-         defineProperties(error, { code });
 
-         if (info) {
 
-             Object.assign(error, info);
 
-         }
 
-         if (error.shortMessage == null) {
 
-             defineProperties(error, { shortMessage });
 
-         }
 
-         return error;
 
-     }
 
-     /**
 
-      *  Throws an EthersError with %%message%%, %%code%% and additional error
 
-      *  %%info%% when %%check%% is falsish..
 
-      *
 
-      *  @see [[api:makeError]]
 
-      */
 
-     function assert(check, message, code, info) {
 
-         if (!check) {
 
-             throw makeError(message, code, info);
 
-         }
 
-     }
 
-     /**
 
-      *  A simple helper to simply ensuring provided arguments match expected
 
-      *  constraints, throwing if not.
 
-      *
 
-      *  In TypeScript environments, the %%check%% has been asserted true, so
 
-      *  any further code does not need additional compile-time checks.
 
-      */
 
-     function assertArgument(check, message, name, value) {
 
-         assert(check, message, "INVALID_ARGUMENT", { argument: name, value: value });
 
-     }
 
-     function assertArgumentCount(count, expectedCount, message) {
 
-         if (message == null) {
 
-             message = "";
 
-         }
 
-         if (message) {
 
-             message = ": " + message;
 
-         }
 
-         assert(count >= expectedCount, "missing argument" + message, "MISSING_ARGUMENT", {
 
-             count: count,
 
-             expectedCount: expectedCount
 
-         });
 
-         assert(count <= expectedCount, "too many arguments" + message, "UNEXPECTED_ARGUMENT", {
 
-             count: count,
 
-             expectedCount: expectedCount
 
-         });
 
-     }
 
-     const _normalizeForms = ["NFD", "NFC", "NFKD", "NFKC"].reduce((accum, form) => {
 
-         try {
 
-             // General test for normalize
 
-             /* c8 ignore start */
 
-             if ("test".normalize(form) !== "test") {
 
-                 throw new Error("bad");
 
-             }
 
-             ;
 
-             /* c8 ignore stop */
 
-             if (form === "NFD") {
 
-                 const check = String.fromCharCode(0xe9).normalize("NFD");
 
-                 const expected = String.fromCharCode(0x65, 0x0301);
 
-                 /* c8 ignore start */
 
-                 if (check !== expected) {
 
-                     throw new Error("broken");
 
-                 }
 
-                 /* c8 ignore stop */
 
-             }
 
-             accum.push(form);
 
-         }
 
-         catch (error) { }
 
-         return accum;
 
-     }, []);
 
-     /**
 
-      *  Throws if the normalization %%form%% is not supported.
 
-      */
 
-     function assertNormalize(form) {
 
-         assert(_normalizeForms.indexOf(form) >= 0, "platform missing String.prototype.normalize", "UNSUPPORTED_OPERATION", {
 
-             operation: "String.prototype.normalize", info: { form }
 
-         });
 
-     }
 
-     /**
 
-      *  Many classes use file-scoped values to guard the constructor,
 
-      *  making it effectively private. This facilitates that pattern
 
-      *  by ensuring the %%givenGaurd%% matches the file-scoped %%guard%%,
 
-      *  throwing if not, indicating the %%className%% if provided.
 
-      */
 
-     function assertPrivate(givenGuard, guard, className) {
 
-         if (className == null) {
 
-             className = "";
 
-         }
 
-         if (givenGuard !== guard) {
 
-             let method = className, operation = "new";
 
-             if (className) {
 
-                 method += ".";
 
-                 operation += " " + className;
 
-             }
 
-             assert(false, `private constructor; use ${method}from* methods`, "UNSUPPORTED_OPERATION", {
 
-                 operation
 
-             });
 
-         }
 
-     }
 
-     /**
 
-      *  Some data helpers.
 
-      *
 
-      *
 
-      *  @_subsection api/utils:Data Helpers  [about-data]
 
-      */
 
-     function _getBytes(value, name, copy) {
 
-         if (value instanceof Uint8Array) {
 
-             if (copy) {
 
-                 return new Uint8Array(value);
 
-             }
 
-             return value;
 
-         }
 
-         if (typeof (value) === "string" && value.match(/^0x(?:[0-9a-f][0-9a-f])*$/i)) {
 
-             const result = new Uint8Array((value.length - 2) / 2);
 
-             let offset = 2;
 
-             for (let i = 0; i < result.length; i++) {
 
-                 result[i] = parseInt(value.substring(offset, offset + 2), 16);
 
-                 offset += 2;
 
-             }
 
-             return result;
 
-         }
 
-         assertArgument(false, "invalid BytesLike value", name || "value", value);
 
-     }
 
-     /**
 
-      *  Get a typed Uint8Array for %%value%%. If already a Uint8Array
 
-      *  the original %%value%% is returned; if a copy is required use
 
-      *  [[getBytesCopy]].
 
-      *
 
-      *  @see: getBytesCopy
 
-      */
 
-     function getBytes(value, name) {
 
-         return _getBytes(value, name, false);
 
-     }
 
-     /**
 
-      *  Get a typed Uint8Array for %%value%%, creating a copy if necessary
 
-      *  to prevent any modifications of the returned value from being
 
-      *  reflected elsewhere.
 
-      *
 
-      *  @see: getBytes
 
-      */
 
-     function getBytesCopy(value, name) {
 
-         return _getBytes(value, name, true);
 
-     }
 
-     /**
 
-      *  Returns true if %%value%% is a valid [[HexString]].
 
-      *
 
-      *  If %%length%% is ``true`` or a //number//, it also checks that
 
-      *  %%value%% is a valid [[DataHexString]] of %%length%% (if a //number//)
 
-      *  bytes of data (e.g. ``0x1234`` is 2 bytes).
 
-      */
 
-     function isHexString(value, length) {
 
-         if (typeof (value) !== "string" || !value.match(/^0x[0-9A-Fa-f]*$/)) {
 
-             return false;
 
-         }
 
-         if (typeof (length) === "number" && value.length !== 2 + 2 * length) {
 
-             return false;
 
-         }
 
-         if (length === true && (value.length % 2) !== 0) {
 
-             return false;
 
-         }
 
-         return true;
 
-     }
 
-     /**
 
-      *  Returns true if %%value%% is a valid representation of arbitrary
 
-      *  data (i.e. a valid [[DataHexString]] or a Uint8Array).
 
-      */
 
-     function isBytesLike(value) {
 
-         return (isHexString(value, true) || (value instanceof Uint8Array));
 
-     }
 
-     const HexCharacters = "0123456789abcdef";
 
-     /**
 
-      *  Returns a [[DataHexString]] representation of %%data%%.
 
-      */
 
-     function hexlify(data) {
 
-         const bytes = getBytes(data);
 
-         let result = "0x";
 
-         for (let i = 0; i < bytes.length; i++) {
 
-             const v = bytes[i];
 
-             result += HexCharacters[(v & 0xf0) >> 4] + HexCharacters[v & 0x0f];
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  Returns a [[DataHexString]] by concatenating all values
 
-      *  within %%data%%.
 
-      */
 
-     function concat(datas) {
 
-         return "0x" + datas.map((d) => hexlify(d).substring(2)).join("");
 
-     }
 
-     /**
 
-      *  Returns the length of %%data%%, in bytes.
 
-      */
 
-     function dataLength(data) {
 
-         if (isHexString(data, true)) {
 
-             return (data.length - 2) / 2;
 
-         }
 
-         return getBytes(data).length;
 
-     }
 
-     /**
 
-      *  Returns a [[DataHexString]] by slicing %%data%% from the %%start%%
 
-      *  offset to the %%end%% offset.
 
-      *
 
-      *  By default %%start%% is 0 and %%end%% is the length of %%data%%.
 
-      */
 
-     function dataSlice(data, start, end) {
 
-         const bytes = getBytes(data);
 
-         if (end != null && end > bytes.length) {
 
-             assert(false, "cannot slice beyond data bounds", "BUFFER_OVERRUN", {
 
-                 buffer: bytes, length: bytes.length, offset: end
 
-             });
 
-         }
 
-         return hexlify(bytes.slice((start == null) ? 0 : start, (end == null) ? bytes.length : end));
 
-     }
 
-     /**
 
-      *  Return the [[DataHexString]] result by stripping all **leading**
 
-      ** zero bytes from %%data%%.
 
-      */
 
-     function stripZerosLeft(data) {
 
-         let bytes = hexlify(data).substring(2);
 
-         while (bytes.startsWith("00")) {
 
-             bytes = bytes.substring(2);
 
-         }
 
-         return "0x" + bytes;
 
-     }
 
-     function zeroPad(data, length, left) {
 
-         const bytes = getBytes(data);
 
-         assert(length >= bytes.length, "padding exceeds data length", "BUFFER_OVERRUN", {
 
-             buffer: new Uint8Array(bytes),
 
-             length: length,
 
-             offset: length + 1
 
-         });
 
-         const result = new Uint8Array(length);
 
-         result.fill(0);
 
-         if (left) {
 
-             result.set(bytes, length - bytes.length);
 
-         }
 
-         else {
 
-             result.set(bytes, 0);
 
-         }
 
-         return hexlify(result);
 
-     }
 
-     /**
 
-      *  Return the [[DataHexString]] of %%data%% padded on the **left**
 
-      *  to %%length%% bytes.
 
-      *
 
-      *  If %%data%% already exceeds %%length%%, a [[BufferOverrunError]] is
 
-      *  thrown.
 
-      *
 
-      *  This pads data the same as **values** are in Solidity
 
-      *  (e.g. ``uint128``).
 
-      */
 
-     function zeroPadValue(data, length) {
 
-         return zeroPad(data, length, true);
 
-     }
 
-     /**
 
-      *  Return the [[DataHexString]] of %%data%% padded on the **right**
 
-      *  to %%length%% bytes.
 
-      *
 
-      *  If %%data%% already exceeds %%length%%, a [[BufferOverrunError]] is
 
-      *  thrown.
 
-      *
 
-      *  This pads data the same as **bytes** are in Solidity
 
-      *  (e.g. ``bytes16``).
 
-      */
 
-     function zeroPadBytes(data, length) {
 
-         return zeroPad(data, length, false);
 
-     }
 
-     /**
 
-      *  Some mathematic operations.
 
-      *
 
-      *  @_subsection: api/utils:Math Helpers  [about-maths]
 
-      */
 
-     const BN_0$a = BigInt(0);
 
-     const BN_1$5 = BigInt(1);
 
-     //const BN_Max256 = (BN_1 << BigInt(256)) - BN_1;
 
-     // IEEE 754 support 53-bits of mantissa
 
-     const maxValue = 0x1fffffffffffff;
 
-     /**
 
-      *  Convert %%value%% from a twos-compliment representation of %%width%%
 
-      *  bits to its value.
 
-      *
 
-      *  If the highest bit is ``1``, the result will be negative.
 
-      */
 
-     function fromTwos(_value, _width) {
 
-         const value = getUint(_value, "value");
 
-         const width = BigInt(getNumber(_width, "width"));
 
-         assert((value >> width) === BN_0$a, "overflow", "NUMERIC_FAULT", {
 
-             operation: "fromTwos", fault: "overflow", value: _value
 
-         });
 
-         // Top bit set; treat as a negative value
 
-         if (value >> (width - BN_1$5)) {
 
-             const mask = (BN_1$5 << width) - BN_1$5;
 
-             return -(((~value) & mask) + BN_1$5);
 
-         }
 
-         return value;
 
-     }
 
-     /**
 
-      *  Convert %%value%% to a twos-compliment representation of
 
-      *  %%width%% bits.
 
-      *
 
-      *  The result will always be positive.
 
-      */
 
-     function toTwos(_value, _width) {
 
-         let value = getBigInt(_value, "value");
 
-         const width = BigInt(getNumber(_width, "width"));
 
-         const limit = (BN_1$5 << (width - BN_1$5));
 
-         if (value < BN_0$a) {
 
-             value = -value;
 
-             assert(value <= limit, "too low", "NUMERIC_FAULT", {
 
-                 operation: "toTwos", fault: "overflow", value: _value
 
-             });
 
-             const mask = (BN_1$5 << width) - BN_1$5;
 
-             return ((~value) & mask) + BN_1$5;
 
-         }
 
-         else {
 
-             assert(value < limit, "too high", "NUMERIC_FAULT", {
 
-                 operation: "toTwos", fault: "overflow", value: _value
 
-             });
 
-         }
 
-         return value;
 
-     }
 
-     /**
 
-      *  Mask %%value%% with a bitmask of %%bits%% ones.
 
-      */
 
-     function mask(_value, _bits) {
 
-         const value = getUint(_value, "value");
 
-         const bits = BigInt(getNumber(_bits, "bits"));
 
-         return value & ((BN_1$5 << bits) - BN_1$5);
 
-     }
 
-     /**
 
-      *  Gets a BigInt from %%value%%. If it is an invalid value for
 
-      *  a BigInt, then an ArgumentError will be thrown for %%name%%.
 
-      */
 
-     function getBigInt(value, name) {
 
-         switch (typeof (value)) {
 
-             case "bigint": return value;
 
-             case "number":
 
-                 assertArgument(Number.isInteger(value), "underflow", name || "value", value);
 
-                 assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
 
-                 return BigInt(value);
 
-             case "string":
 
-                 try {
 
-                     if (value === "") {
 
-                         throw new Error("empty string");
 
-                     }
 
-                     if (value[0] === "-" && value[1] !== "-") {
 
-                         return -BigInt(value.substring(1));
 
-                     }
 
-                     return BigInt(value);
 
-                 }
 
-                 catch (e) {
 
-                     assertArgument(false, `invalid BigNumberish string: ${e.message}`, name || "value", value);
 
-                 }
 
-         }
 
-         assertArgument(false, "invalid BigNumberish value", name || "value", value);
 
-     }
 
-     /**
 
-      *  Returns %%value%% as a bigint, validating it is valid as a bigint
 
-      *  value and that it is positive.
 
-      */
 
-     function getUint(value, name) {
 
-         const result = getBigInt(value, name);
 
-         assert(result >= BN_0$a, "unsigned value cannot be negative", "NUMERIC_FAULT", {
 
-             fault: "overflow", operation: "getUint", value
 
-         });
 
-         return result;
 
-     }
 
-     const Nibbles$1 = "0123456789abcdef";
 
-     /*
 
-      * Converts %%value%% to a BigInt. If %%value%% is a Uint8Array, it
 
-      * is treated as Big Endian data.
 
-      */
 
-     function toBigInt(value) {
 
-         if (value instanceof Uint8Array) {
 
-             let result = "0x0";
 
-             for (const v of value) {
 
-                 result += Nibbles$1[v >> 4];
 
-                 result += Nibbles$1[v & 0x0f];
 
-             }
 
-             return BigInt(result);
 
-         }
 
-         return getBigInt(value);
 
-     }
 
-     /**
 
-      *  Gets a //number// from %%value%%. If it is an invalid value for
 
-      *  a //number//, then an ArgumentError will be thrown for %%name%%.
 
-      */
 
-     function getNumber(value, name) {
 
-         switch (typeof (value)) {
 
-             case "bigint":
 
-                 assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
 
-                 return Number(value);
 
-             case "number":
 
-                 assertArgument(Number.isInteger(value), "underflow", name || "value", value);
 
-                 assertArgument(value >= -maxValue && value <= maxValue, "overflow", name || "value", value);
 
-                 return value;
 
-             case "string":
 
-                 try {
 
-                     if (value === "") {
 
-                         throw new Error("empty string");
 
-                     }
 
-                     return getNumber(BigInt(value), name);
 
-                 }
 
-                 catch (e) {
 
-                     assertArgument(false, `invalid numeric string: ${e.message}`, name || "value", value);
 
-                 }
 
-         }
 
-         assertArgument(false, "invalid numeric value", name || "value", value);
 
-     }
 
-     /**
 
-      *  Converts %%value%% to a number. If %%value%% is a Uint8Array, it
 
-      *  is treated as Big Endian data. Throws if the value is not safe.
 
-      */
 
-     function toNumber(value) {
 
-         return getNumber(toBigInt(value));
 
-     }
 
-     /**
 
-      *  Converts %%value%% to a Big Endian hexstring, optionally padded to
 
-      *  %%width%% bytes.
 
-      */
 
-     function toBeHex(_value, _width) {
 
-         const value = getUint(_value, "value");
 
-         let result = value.toString(16);
 
-         if (_width == null) {
 
-             // Ensure the value is of even length
 
-             if (result.length % 2) {
 
-                 result = "0" + result;
 
-             }
 
-         }
 
-         else {
 
-             const width = getNumber(_width, "width");
 
-             assert(width * 2 >= result.length, `value exceeds width (${width} bytes)`, "NUMERIC_FAULT", {
 
-                 operation: "toBeHex",
 
-                 fault: "overflow",
 
-                 value: _value
 
-             });
 
-             // Pad the value to the required width
 
-             while (result.length < (width * 2)) {
 
-                 result = "0" + result;
 
-             }
 
-         }
 
-         return "0x" + result;
 
-     }
 
-     /**
 
-      *  Converts %%value%% to a Big Endian Uint8Array.
 
-      */
 
-     function toBeArray(_value) {
 
-         const value = getUint(_value, "value");
 
-         if (value === BN_0$a) {
 
-             return new Uint8Array([]);
 
-         }
 
-         let hex = value.toString(16);
 
-         if (hex.length % 2) {
 
-             hex = "0" + hex;
 
-         }
 
-         const result = new Uint8Array(hex.length / 2);
 
-         for (let i = 0; i < result.length; i++) {
 
-             const offset = i * 2;
 
-             result[i] = parseInt(hex.substring(offset, offset + 2), 16);
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  Returns a [[HexString]] for %%value%% safe to use as a //Quantity//.
 
-      *
 
-      *  A //Quantity// does not have and leading 0 values unless the value is
 
-      *  the literal value `0x0`. This is most commonly used for JSSON-RPC
 
-      *  numeric values.
 
-      */
 
-     function toQuantity(value) {
 
-         let result = hexlify(isBytesLike(value) ? value : toBeArray(value)).substring(2);
 
-         while (result.startsWith("0")) {
 
-             result = result.substring(1);
 
-         }
 
-         if (result === "") {
 
-             result = "0";
 
-         }
 
-         return "0x" + result;
 
-     }
 
-     /**
 
-      *  The [Base58 Encoding](link-base58) scheme allows a **numeric** value
 
-      *  to be encoded as a compact string using a radix of 58 using only
 
-      *  alpha-numeric characters. Confusingly similar characters are omitted
 
-      *  (i.e. ``"l0O"``).
 
-      *
 
-      *  Note that Base58 encodes a **numeric** value, not arbitrary bytes,
 
-      *  since any zero-bytes on the left would get removed. To mitigate this
 
-      *  issue most schemes that use Base58 choose specific high-order values
 
-      *  to ensure non-zero prefixes.
 
-      *
 
-      *  @_subsection: api/utils:Base58 Encoding [about-base58]
 
-      */
 
-     const Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
 
-     let Lookup = null;
 
-     function getAlpha(letter) {
 
-         if (Lookup == null) {
 
-             Lookup = {};
 
-             for (let i = 0; i < Alphabet.length; i++) {
 
-                 Lookup[Alphabet[i]] = BigInt(i);
 
-             }
 
-         }
 
-         const result = Lookup[letter];
 
-         assertArgument(result != null, `invalid base58 value`, "letter", letter);
 
-         return result;
 
-     }
 
-     const BN_0$9 = BigInt(0);
 
-     const BN_58 = BigInt(58);
 
-     /**
 
-      *  Encode %%value%% as a Base58-encoded string.
 
-      */
 
-     function encodeBase58(_value) {
 
-         const bytes = getBytes(_value);
 
-         let value = toBigInt(bytes);
 
-         let result = "";
 
-         while (value) {
 
-             result = Alphabet[Number(value % BN_58)] + result;
 
-             value /= BN_58;
 
-         }
 
-         // Account for leading padding zeros
 
-         for (let i = 0; i < bytes.length; i++) {
 
-             if (bytes[i]) {
 
-                 break;
 
-             }
 
-             result = Alphabet[0] + result;
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  Decode the Base58-encoded %%value%%.
 
-      */
 
-     function decodeBase58(value) {
 
-         let result = BN_0$9;
 
-         for (let i = 0; i < value.length; i++) {
 
-             result *= BN_58;
 
-             result += getAlpha(value[i]);
 
-         }
 
-         return result;
 
-     }
 
-     // utils/base64-browser
 
-     function decodeBase64(textData) {
 
-         textData = atob(textData);
 
-         const data = new Uint8Array(textData.length);
 
-         for (let i = 0; i < textData.length; i++) {
 
-             data[i] = textData.charCodeAt(i);
 
-         }
 
-         return getBytes(data);
 
-     }
 
-     function encodeBase64(_data) {
 
-         const data = getBytes(_data);
 
-         let textData = "";
 
-         for (let i = 0; i < data.length; i++) {
 
-             textData += String.fromCharCode(data[i]);
 
-         }
 
-         return btoa(textData);
 
-     }
 
-     /**
 
-      *  Events allow for applications to use the observer pattern, which
 
-      *  allows subscribing and publishing events, outside the normal
 
-      *  execution paths.
 
-      *
 
-      *  @_section api/utils/events:Events  [about-events]
 
-      */
 
-     /**
 
-      *  When an [[EventEmitterable]] triggers a [[Listener]], the
 
-      *  callback always ahas one additional argument passed, which is
 
-      *  an **EventPayload**.
 
-      */
 
-     class EventPayload {
 
-         /**
 
-          *  The event filter.
 
-          */
 
-         filter;
 
-         /**
 
-          *  The **EventEmitterable**.
 
-          */
 
-         emitter;
 
-         #listener;
 
-         /**
 
-          *  Create a new **EventPayload** for %%emitter%% with
 
-          *  the %%listener%% and for %%filter%%.
 
-          */
 
-         constructor(emitter, listener, filter) {
 
-             this.#listener = listener;
 
-             defineProperties(this, { emitter, filter });
 
-         }
 
-         /**
 
-          *  Unregister the triggered listener for future events.
 
-          */
 
-         async removeListener() {
 
-             if (this.#listener == null) {
 
-                 return;
 
-             }
 
-             await this.emitter.off(this.filter, this.#listener);
 
-         }
 
-     }
 
-     /**
 
-      *  Using strings in Ethereum (or any security-basd system) requires
 
-      *  additional care. These utilities attempt to mitigate some of the
 
-      *  safety issues as well as provide the ability to recover and analyse
 
-      *  strings.
 
-      *
 
-      *  @_subsection api/utils:Strings and UTF-8  [about-strings]
 
-      */
 
-     function errorFunc(reason, offset, bytes, output, badCodepoint) {
 
-         assertArgument(false, `invalid codepoint at offset ${offset}; ${reason}`, "bytes", bytes);
 
-     }
 
-     function ignoreFunc(reason, offset, bytes, output, badCodepoint) {
 
-         // If there is an invalid prefix (including stray continuation), skip any additional continuation bytes
 
-         if (reason === "BAD_PREFIX" || reason === "UNEXPECTED_CONTINUE") {
 
-             let i = 0;
 
-             for (let o = offset + 1; o < bytes.length; o++) {
 
-                 if (bytes[o] >> 6 !== 0x02) {
 
-                     break;
 
-                 }
 
-                 i++;
 
-             }
 
-             return i;
 
-         }
 
-         // This byte runs us past the end of the string, so just jump to the end
 
-         // (but the first byte was read already read and therefore skipped)
 
-         if (reason === "OVERRUN") {
 
-             return bytes.length - offset - 1;
 
-         }
 
-         // Nothing to skip
 
-         return 0;
 
-     }
 
-     function replaceFunc(reason, offset, bytes, output, badCodepoint) {
 
-         // Overlong representations are otherwise "valid" code points; just non-deistingtished
 
-         if (reason === "OVERLONG") {
 
-             assertArgument(typeof (badCodepoint) === "number", "invalid bad code point for replacement", "badCodepoint", badCodepoint);
 
-             output.push(badCodepoint);
 
-             return 0;
 
-         }
 
-         // Put the replacement character into the output
 
-         output.push(0xfffd);
 
-         // Otherwise, process as if ignoring errors
 
-         return ignoreFunc(reason, offset, bytes);
 
-     }
 
-     /**
 
-      *  A handful of popular, built-in UTF-8 error handling strategies.
 
-      *
 
-      *  **``"error"``** - throws on ANY illegal UTF-8 sequence or
 
-      *  non-canonical (overlong) codepoints (this is the default)
 
-      *
 
-      *  **``"ignore"``** - silently drops any illegal UTF-8 sequence
 
-      *  and accepts non-canonical (overlong) codepoints
 
-      *
 
-      *  **``"replace"``** - replace any illegal UTF-8 sequence with the
 
-      *  UTF-8 replacement character (i.e. ``"\\ufffd"``) and accepts
 
-      *  non-canonical (overlong) codepoints
 
-      *
 
-      *  @returns: Record<"error" | "ignore" | "replace", Utf8ErrorFunc>
 
-      */
 
-     const Utf8ErrorFuncs = Object.freeze({
 
-         error: errorFunc,
 
-         ignore: ignoreFunc,
 
-         replace: replaceFunc
 
-     });
 
-     // http://stackoverflow.com/questions/13356493/decode-utf-8-with-javascript#13691499
 
-     function getUtf8CodePoints(_bytes, onError) {
 
-         if (onError == null) {
 
-             onError = Utf8ErrorFuncs.error;
 
-         }
 
-         const bytes = getBytes(_bytes, "bytes");
 
-         const result = [];
 
-         let i = 0;
 
-         // Invalid bytes are ignored
 
-         while (i < bytes.length) {
 
-             const c = bytes[i++];
 
-             // 0xxx xxxx
 
-             if (c >> 7 === 0) {
 
-                 result.push(c);
 
-                 continue;
 
-             }
 
-             // Multibyte; how many bytes left for this character?
 
-             let extraLength = null;
 
-             let overlongMask = null;
 
-             // 110x xxxx 10xx xxxx
 
-             if ((c & 0xe0) === 0xc0) {
 
-                 extraLength = 1;
 
-                 overlongMask = 0x7f;
 
-                 // 1110 xxxx 10xx xxxx 10xx xxxx
 
-             }
 
-             else if ((c & 0xf0) === 0xe0) {
 
-                 extraLength = 2;
 
-                 overlongMask = 0x7ff;
 
-                 // 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
 
-             }
 
-             else if ((c & 0xf8) === 0xf0) {
 
-                 extraLength = 3;
 
-                 overlongMask = 0xffff;
 
-             }
 
-             else {
 
-                 if ((c & 0xc0) === 0x80) {
 
-                     i += onError("UNEXPECTED_CONTINUE", i - 1, bytes, result);
 
-                 }
 
-                 else {
 
-                     i += onError("BAD_PREFIX", i - 1, bytes, result);
 
-                 }
 
-                 continue;
 
-             }
 
-             // Do we have enough bytes in our data?
 
-             if (i - 1 + extraLength >= bytes.length) {
 
-                 i += onError("OVERRUN", i - 1, bytes, result);
 
-                 continue;
 
-             }
 
-             // Remove the length prefix from the char
 
-             let res = c & ((1 << (8 - extraLength - 1)) - 1);
 
-             for (let j = 0; j < extraLength; j++) {
 
-                 let nextChar = bytes[i];
 
-                 // Invalid continuation byte
 
-                 if ((nextChar & 0xc0) != 0x80) {
 
-                     i += onError("MISSING_CONTINUE", i, bytes, result);
 
-                     res = null;
 
-                     break;
 
-                 }
 
-                 res = (res << 6) | (nextChar & 0x3f);
 
-                 i++;
 
-             }
 
-             // See above loop for invalid continuation byte
 
-             if (res === null) {
 
-                 continue;
 
-             }
 
-             // Maximum code point
 
-             if (res > 0x10ffff) {
 
-                 i += onError("OUT_OF_RANGE", i - 1 - extraLength, bytes, result, res);
 
-                 continue;
 
-             }
 
-             // Reserved for UTF-16 surrogate halves
 
-             if (res >= 0xd800 && res <= 0xdfff) {
 
-                 i += onError("UTF16_SURROGATE", i - 1 - extraLength, bytes, result, res);
 
-                 continue;
 
-             }
 
-             // Check for overlong sequences (more bytes than needed)
 
-             if (res <= overlongMask) {
 
-                 i += onError("OVERLONG", i - 1 - extraLength, bytes, result, res);
 
-                 continue;
 
-             }
 
-             result.push(res);
 
-         }
 
-         return result;
 
-     }
 
-     // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
 
-     /**
 
-      *  Returns the UTF-8 byte representation of %%str%%.
 
-      *
 
-      *  If %%form%% is specified, the string is normalized.
 
-      */
 
-     function toUtf8Bytes(str, form) {
 
-         assertArgument(typeof (str) === "string", "invalid string value", "str", str);
 
-         if (form != null) {
 
-             assertNormalize(form);
 
-             str = str.normalize(form);
 
-         }
 
-         let result = [];
 
-         for (let i = 0; i < str.length; i++) {
 
-             const c = str.charCodeAt(i);
 
-             if (c < 0x80) {
 
-                 result.push(c);
 
-             }
 
-             else if (c < 0x800) {
 
-                 result.push((c >> 6) | 0xc0);
 
-                 result.push((c & 0x3f) | 0x80);
 
-             }
 
-             else if ((c & 0xfc00) == 0xd800) {
 
-                 i++;
 
-                 const c2 = str.charCodeAt(i);
 
-                 assertArgument(i < str.length && ((c2 & 0xfc00) === 0xdc00), "invalid surrogate pair", "str", str);
 
-                 // Surrogate Pair
 
-                 const pair = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
 
-                 result.push((pair >> 18) | 0xf0);
 
-                 result.push(((pair >> 12) & 0x3f) | 0x80);
 
-                 result.push(((pair >> 6) & 0x3f) | 0x80);
 
-                 result.push((pair & 0x3f) | 0x80);
 
-             }
 
-             else {
 
-                 result.push((c >> 12) | 0xe0);
 
-                 result.push(((c >> 6) & 0x3f) | 0x80);
 
-                 result.push((c & 0x3f) | 0x80);
 
-             }
 
-         }
 
-         return new Uint8Array(result);
 
-     }
 
-     //export 
 
-     function _toUtf8String(codePoints) {
 
-         return codePoints.map((codePoint) => {
 
-             if (codePoint <= 0xffff) {
 
-                 return String.fromCharCode(codePoint);
 
-             }
 
-             codePoint -= 0x10000;
 
-             return String.fromCharCode((((codePoint >> 10) & 0x3ff) + 0xd800), ((codePoint & 0x3ff) + 0xdc00));
 
-         }).join("");
 
-     }
 
-     /**
 
-      *  Returns the string represented by the UTF-8 data %%bytes%%.
 
-      *
 
-      *  When %%onError%% function is specified, it is called on UTF-8
 
-      *  errors allowing recovery using the [[Utf8ErrorFunc]] API.
 
-      *  (default: [error](Utf8ErrorFuncs))
 
-      */
 
-     function toUtf8String(bytes, onError) {
 
-         return _toUtf8String(getUtf8CodePoints(bytes, onError));
 
-     }
 
-     /**
 
-      *  Returns the UTF-8 code-points for %%str%%.
 
-      *
 
-      *  If %%form%% is specified, the string is normalized.
 
-      */
 
-     function toUtf8CodePoints(str, form) {
 
-         return getUtf8CodePoints(toUtf8Bytes(str, form));
 
-     }
 
-     function createGetUrl(options) {
 
-         async function getUrl(req, _signal) {
 
-             assert(_signal == null || !_signal.cancelled, "request cancelled before sending", "CANCELLED");
 
-             const protocol = req.url.split(":")[0].toLowerCase();
 
-             assert(protocol === "http" || protocol === "https", `unsupported protocol ${protocol}`, "UNSUPPORTED_OPERATION", {
 
-                 info: { protocol },
 
-                 operation: "request"
 
-             });
 
-             assert(protocol === "https" || !req.credentials || req.allowInsecureAuthentication, "insecure authorized connections unsupported", "UNSUPPORTED_OPERATION", {
 
-                 operation: "request"
 
-             });
 
-             let error = null;
 
-             const controller = new AbortController();
 
-             const timer = setTimeout(() => {
 
-                 error = makeError("request timeout", "TIMEOUT");
 
-                 controller.abort();
 
-             }, req.timeout);
 
-             if (_signal) {
 
-                 _signal.addListener(() => {
 
-                     error = makeError("request cancelled", "CANCELLED");
 
-                     controller.abort();
 
-                 });
 
-             }
 
-             const init = {
 
-                 method: req.method,
 
-                 headers: new Headers(Array.from(req)),
 
-                 body: req.body || undefined,
 
-                 signal: controller.signal
 
-             };
 
-             let resp;
 
-             try {
 
-                 resp = await fetch(req.url, init);
 
-             }
 
-             catch (_error) {
 
-                 clearTimeout(timer);
 
-                 if (error) {
 
-                     throw error;
 
-                 }
 
-                 throw _error;
 
-             }
 
-             clearTimeout(timer);
 
-             const headers = {};
 
-             resp.headers.forEach((value, key) => {
 
-                 headers[key.toLowerCase()] = value;
 
-             });
 
-             const respBody = await resp.arrayBuffer();
 
-             const body = (respBody == null) ? null : new Uint8Array(respBody);
 
-             return {
 
-                 statusCode: resp.status,
 
-                 statusMessage: resp.statusText,
 
-                 headers, body
 
-             };
 
-         }
 
-         return getUrl;
 
-     }
 
-     /**
 
-      *  Fetching content from the web is environment-specific, so Ethers
 
-      *  provides an abstraction that each environment can implement to provide
 
-      *  this service.
 
-      *
 
-      *  On [Node.js](link-node), the ``http`` and ``https`` libs are used to
 
-      *  create a request object, register event listeners and process data
 
-      *  and populate the [[FetchResponse]].
 
-      *
 
-      *  In a browser, the [DOM fetch](link-js-fetch) is used, and the resulting
 
-      *  ``Promise`` is waited on to retrieve the payload.
 
-      *
 
-      *  The [[FetchRequest]] is responsible for handling many common situations,
 
-      *  such as redirects, server throttling, authentication, etc.
 
-      *
 
-      *  It also handles common gateways, such as IPFS and data URIs.
 
-      *
 
-      *  @_section api/utils/fetching:Fetching Web Content  [about-fetch]
 
-      */
 
-     const MAX_ATTEMPTS = 12;
 
-     const SLOT_INTERVAL = 250;
 
-     // The global FetchGetUrlFunc implementation.
 
-     let defaultGetUrlFunc = createGetUrl();
 
-     const reData = new RegExp("^data:([^;:]*)?(;base64)?,(.*)$", "i");
 
-     const reIpfs = new RegExp("^ipfs:/\/(ipfs/)?(.*)$", "i");
 
-     // If locked, new Gateways cannot be added
 
-     let locked$5 = false;
 
-     // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
 
-     async function dataGatewayFunc(url, signal) {
 
-         try {
 
-             const match = url.match(reData);
 
-             if (!match) {
 
-                 throw new Error("invalid data");
 
-             }
 
-             return new FetchResponse(200, "OK", {
 
-                 "content-type": (match[1] || "text/plain"),
 
-             }, (match[2] ? decodeBase64(match[3]) : unpercent(match[3])));
 
-         }
 
-         catch (error) {
 
-             return new FetchResponse(599, "BAD REQUEST (invalid data: URI)", {}, null, new FetchRequest(url));
 
-         }
 
-     }
 
-     /**
 
-      *  Returns a [[FetchGatewayFunc]] for fetching content from a standard
 
-      *  IPFS gateway hosted at %%baseUrl%%.
 
-      */
 
-     function getIpfsGatewayFunc(baseUrl) {
 
-         async function gatewayIpfs(url, signal) {
 
-             try {
 
-                 const match = url.match(reIpfs);
 
-                 if (!match) {
 
-                     throw new Error("invalid link");
 
-                 }
 
-                 return new FetchRequest(`${baseUrl}${match[2]}`);
 
-             }
 
-             catch (error) {
 
-                 return new FetchResponse(599, "BAD REQUEST (invalid IPFS URI)", {}, null, new FetchRequest(url));
 
-             }
 
-         }
 
-         return gatewayIpfs;
 
-     }
 
-     const Gateways = {
 
-         "data": dataGatewayFunc,
 
-         "ipfs": getIpfsGatewayFunc("https:/\/gateway.ipfs.io/ipfs/")
 
-     };
 
-     const fetchSignals = new WeakMap();
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class FetchCancelSignal {
 
-         #listeners;
 
-         #cancelled;
 
-         constructor(request) {
 
-             this.#listeners = [];
 
-             this.#cancelled = false;
 
-             fetchSignals.set(request, () => {
 
-                 if (this.#cancelled) {
 
-                     return;
 
-                 }
 
-                 this.#cancelled = true;
 
-                 for (const listener of this.#listeners) {
 
-                     setTimeout(() => { listener(); }, 0);
 
-                 }
 
-                 this.#listeners = [];
 
-             });
 
-         }
 
-         addListener(listener) {
 
-             assert(!this.#cancelled, "singal already cancelled", "UNSUPPORTED_OPERATION", {
 
-                 operation: "fetchCancelSignal.addCancelListener"
 
-             });
 
-             this.#listeners.push(listener);
 
-         }
 
-         get cancelled() { return this.#cancelled; }
 
-         checkSignal() {
 
-             assert(!this.cancelled, "cancelled", "CANCELLED", {});
 
-         }
 
-     }
 
-     // Check the signal, throwing if it is cancelled
 
-     function checkSignal(signal) {
 
-         if (signal == null) {
 
-             throw new Error("missing signal; should not happen");
 
-         }
 
-         signal.checkSignal();
 
-         return signal;
 
-     }
 
-     /**
 
-      *  Represents a request for a resource using a URI.
 
-      *
 
-      *  By default, the supported schemes are ``HTTP``, ``HTTPS``, ``data:``,
 
-      *  and ``IPFS:``.
 
-      *
 
-      *  Additional schemes can be added globally using [[registerGateway]].
 
-      *
 
-      *  @example:
 
-      *    req = new FetchRequest("https://www.ricmoo.com")
 
-      *    resp = await req.send()
 
-      *    resp.body.length
 
-      *    //_result:
 
-      */
 
-     class FetchRequest {
 
-         #allowInsecure;
 
-         #gzip;
 
-         #headers;
 
-         #method;
 
-         #timeout;
 
-         #url;
 
-         #body;
 
-         #bodyType;
 
-         #creds;
 
-         // Hooks
 
-         #preflight;
 
-         #process;
 
-         #retry;
 
-         #signal;
 
-         #throttle;
 
-         #getUrlFunc;
 
-         /**
 
-          *  The fetch URL to request.
 
-          */
 
-         get url() { return this.#url; }
 
-         set url(url) {
 
-             this.#url = String(url);
 
-         }
 
-         /**
 
-          *  The fetch body, if any, to send as the request body. //(default: null)//
 
-          *
 
-          *  When setting a body, the intrinsic ``Content-Type`` is automatically
 
-          *  set and will be used if **not overridden** by setting a custom
 
-          *  header.
 
-          *
 
-          *  If %%body%% is null, the body is cleared (along with the
 
-          *  intrinsic ``Content-Type``).
 
-          *
 
-          *  If %%body%% is a string, the intrinsic ``Content-Type`` is set to
 
-          *  ``text/plain``.
 
-          *
 
-          *  If %%body%% is a Uint8Array, the intrinsic ``Content-Type`` is set to
 
-          *  ``application/octet-stream``.
 
-          *
 
-          *  If %%body%% is any other object, the intrinsic ``Content-Type`` is
 
-          *  set to ``application/json``.
 
-          */
 
-         get body() {
 
-             if (this.#body == null) {
 
-                 return null;
 
-             }
 
-             return new Uint8Array(this.#body);
 
-         }
 
-         set body(body) {
 
-             if (body == null) {
 
-                 this.#body = undefined;
 
-                 this.#bodyType = undefined;
 
-             }
 
-             else if (typeof (body) === "string") {
 
-                 this.#body = toUtf8Bytes(body);
 
-                 this.#bodyType = "text/plain";
 
-             }
 
-             else if (body instanceof Uint8Array) {
 
-                 this.#body = body;
 
-                 this.#bodyType = "application/octet-stream";
 
-             }
 
-             else if (typeof (body) === "object") {
 
-                 this.#body = toUtf8Bytes(JSON.stringify(body));
 
-                 this.#bodyType = "application/json";
 
-             }
 
-             else {
 
-                 throw new Error("invalid body");
 
-             }
 
-         }
 
-         /**
 
-          *  Returns true if the request has a body.
 
-          */
 
-         hasBody() {
 
-             return (this.#body != null);
 
-         }
 
-         /**
 
-          *  The HTTP method to use when requesting the URI. If no method
 
-          *  has been explicitly set, then ``GET`` is used if the body is
 
-          *  null and ``POST`` otherwise.
 
-          */
 
-         get method() {
 
-             if (this.#method) {
 
-                 return this.#method;
 
-             }
 
-             if (this.hasBody()) {
 
-                 return "POST";
 
-             }
 
-             return "GET";
 
-         }
 
-         set method(method) {
 
-             if (method == null) {
 
-                 method = "";
 
-             }
 
-             this.#method = String(method).toUpperCase();
 
-         }
 
-         /**
 
-          *  The headers that will be used when requesting the URI. All
 
-          *  keys are lower-case.
 
-          *
 
-          *  This object is a copy, so any changes will **NOT** be reflected
 
-          *  in the ``FetchRequest``.
 
-          *
 
-          *  To set a header entry, use the ``setHeader`` method.
 
-          */
 
-         get headers() {
 
-             const headers = Object.assign({}, this.#headers);
 
-             if (this.#creds) {
 
-                 headers["authorization"] = `Basic ${encodeBase64(toUtf8Bytes(this.#creds))}`;
 
-             }
 
-             if (this.allowGzip) {
 
-                 headers["accept-encoding"] = "gzip";
 
-             }
 
-             if (headers["content-type"] == null && this.#bodyType) {
 
-                 headers["content-type"] = this.#bodyType;
 
-             }
 
-             if (this.body) {
 
-                 headers["content-length"] = String(this.body.length);
 
-             }
 
-             return headers;
 
-         }
 
-         /**
 
-          *  Get the header for %%key%%, ignoring case.
 
-          */
 
-         getHeader(key) {
 
-             return this.headers[key.toLowerCase()];
 
-         }
 
-         /**
 
-          *  Set the header for %%key%% to %%value%%. All values are coerced
 
-          *  to a string.
 
-          */
 
-         setHeader(key, value) {
 
-             this.#headers[String(key).toLowerCase()] = String(value);
 
-         }
 
-         /**
 
-          *  Clear all headers, resetting all intrinsic headers.
 
-          */
 
-         clearHeaders() {
 
-             this.#headers = {};
 
-         }
 
-         [Symbol.iterator]() {
 
-             const headers = this.headers;
 
-             const keys = Object.keys(headers);
 
-             let index = 0;
 
-             return {
 
-                 next: () => {
 
-                     if (index < keys.length) {
 
-                         const key = keys[index++];
 
-                         return {
 
-                             value: [key, headers[key]], done: false
 
-                         };
 
-                     }
 
-                     return { value: undefined, done: true };
 
-                 }
 
-             };
 
-         }
 
-         /**
 
-          *  The value that will be sent for the ``Authorization`` header.
 
-          *
 
-          *  To set the credentials, use the ``setCredentials`` method.
 
-          */
 
-         get credentials() {
 
-             return this.#creds || null;
 
-         }
 
-         /**
 
-          *  Sets an ``Authorization`` for %%username%% with %%password%%.
 
-          */
 
-         setCredentials(username, password) {
 
-             assertArgument(!username.match(/:/), "invalid basic authentication username", "username", "[REDACTED]");
 
-             this.#creds = `${username}:${password}`;
 
-         }
 
-         /**
 
-          *  Enable and request gzip-encoded responses. The response will
 
-          *  automatically be decompressed. //(default: true)//
 
-          */
 
-         get allowGzip() {
 
-             return this.#gzip;
 
-         }
 
-         set allowGzip(value) {
 
-             this.#gzip = !!value;
 
-         }
 
-         /**
 
-          *  Allow ``Authentication`` credentials to be sent over insecure
 
-          *  channels. //(default: false)//
 
-          */
 
-         get allowInsecureAuthentication() {
 
-             return !!this.#allowInsecure;
 
-         }
 
-         set allowInsecureAuthentication(value) {
 
-             this.#allowInsecure = !!value;
 
-         }
 
-         /**
 
-          *  The timeout (in milliseconds) to wait for a complete response.
 
-          *  //(default: 5 minutes)//
 
-          */
 
-         get timeout() { return this.#timeout; }
 
-         set timeout(timeout) {
 
-             assertArgument(timeout >= 0, "timeout must be non-zero", "timeout", timeout);
 
-             this.#timeout = timeout;
 
-         }
 
-         /**
 
-          *  This function is called prior to each request, for example
 
-          *  during a redirection or retry in case of server throttling.
 
-          *
 
-          *  This offers an opportunity to populate headers or update
 
-          *  content before sending a request.
 
-          */
 
-         get preflightFunc() {
 
-             return this.#preflight || null;
 
-         }
 
-         set preflightFunc(preflight) {
 
-             this.#preflight = preflight;
 
-         }
 
-         /**
 
-          *  This function is called after each response, offering an
 
-          *  opportunity to provide client-level throttling or updating
 
-          *  response data.
 
-          *
 
-          *  Any error thrown in this causes the ``send()`` to throw.
 
-          *
 
-          *  To schedule a retry attempt (assuming the maximum retry limit
 
-          *  has not been reached), use [[response.throwThrottleError]].
 
-          */
 
-         get processFunc() {
 
-             return this.#process || null;
 
-         }
 
-         set processFunc(process) {
 
-             this.#process = process;
 
-         }
 
-         /**
 
-          *  This function is called on each retry attempt.
 
-          */
 
-         get retryFunc() {
 
-             return this.#retry || null;
 
-         }
 
-         set retryFunc(retry) {
 
-             this.#retry = retry;
 
-         }
 
-         /**
 
-          *  This function is called to fetch content from HTTP and
 
-          *  HTTPS URLs and is platform specific (e.g. nodejs vs
 
-          *  browsers).
 
-          *
 
-          *  This is by default the currently registered global getUrl
 
-          *  function, which can be changed using [[registerGetUrl]].
 
-          *  If this has been set, setting is to ``null`` will cause
 
-          *  this FetchRequest (and any future clones) to revert back to
 
-          *  using the currently registered global getUrl function.
 
-          *
 
-          *  Setting this is generally not necessary, but may be useful
 
-          *  for developers that wish to intercept requests or to
 
-          *  configurege a proxy or other agent.
 
-          */
 
-         get getUrlFunc() {
 
-             return this.#getUrlFunc || defaultGetUrlFunc;
 
-         }
 
-         set getUrlFunc(value) {
 
-             this.#getUrlFunc = value;
 
-         }
 
-         /**
 
-          *  Create a new FetchRequest instance with default values.
 
-          *
 
-          *  Once created, each property may be set before issuing a
 
-          *  ``.send()`` to make the request.
 
-          */
 
-         constructor(url) {
 
-             this.#url = String(url);
 
-             this.#allowInsecure = false;
 
-             this.#gzip = true;
 
-             this.#headers = {};
 
-             this.#method = "";
 
-             this.#timeout = 300000;
 
-             this.#throttle = {
 
-                 slotInterval: SLOT_INTERVAL,
 
-                 maxAttempts: MAX_ATTEMPTS
 
-             };
 
-             this.#getUrlFunc = null;
 
-         }
 
-         toString() {
 
-             return `<FetchRequest method=${JSON.stringify(this.method)} url=${JSON.stringify(this.url)} headers=${JSON.stringify(this.headers)} body=${this.#body ? hexlify(this.#body) : "null"}>`;
 
-         }
 
-         /**
 
-          *  Update the throttle parameters used to determine maximum
 
-          *  attempts and exponential-backoff properties.
 
-          */
 
-         setThrottleParams(params) {
 
-             if (params.slotInterval != null) {
 
-                 this.#throttle.slotInterval = params.slotInterval;
 
-             }
 
-             if (params.maxAttempts != null) {
 
-                 this.#throttle.maxAttempts = params.maxAttempts;
 
-             }
 
-         }
 
-         async #send(attempt, expires, delay, _request, _response) {
 
-             if (attempt >= this.#throttle.maxAttempts) {
 
-                 return _response.makeServerError("exceeded maximum retry limit");
 
-             }
 
-             assert(getTime$2() <= expires, "timeout", "TIMEOUT", {
 
-                 operation: "request.send", reason: "timeout", request: _request
 
-             });
 
-             if (delay > 0) {
 
-                 await wait(delay);
 
-             }
 
-             let req = this.clone();
 
-             const scheme = (req.url.split(":")[0] || "").toLowerCase();
 
-             // Process any Gateways
 
-             if (scheme in Gateways) {
 
-                 const result = await Gateways[scheme](req.url, checkSignal(_request.#signal));
 
-                 if (result instanceof FetchResponse) {
 
-                     let response = result;
 
-                     if (this.processFunc) {
 
-                         checkSignal(_request.#signal);
 
-                         try {
 
-                             response = await this.processFunc(req, response);
 
-                         }
 
-                         catch (error) {
 
-                             // Something went wrong during processing; throw a 5xx server error
 
-                             if (error.throttle == null || typeof (error.stall) !== "number") {
 
-                                 response.makeServerError("error in post-processing function", error).assertOk();
 
-                             }
 
-                             // Ignore throttling
 
-                         }
 
-                     }
 
-                     return response;
 
-                 }
 
-                 req = result;
 
-             }
 
-             // We have a preflight function; update the request
 
-             if (this.preflightFunc) {
 
-                 req = await this.preflightFunc(req);
 
-             }
 
-             const resp = await this.getUrlFunc(req, checkSignal(_request.#signal));
 
-             let response = new FetchResponse(resp.statusCode, resp.statusMessage, resp.headers, resp.body, _request);
 
-             if (response.statusCode === 301 || response.statusCode === 302) {
 
-                 // Redirect
 
-                 try {
 
-                     const location = response.headers.location || "";
 
-                     return req.redirect(location).#send(attempt + 1, expires, 0, _request, response);
 
-                 }
 
-                 catch (error) { }
 
-                 // Things won't get any better on another attempt; abort
 
-                 return response;
 
-             }
 
-             else if (response.statusCode === 429) {
 
-                 // Throttle
 
-                 if (this.retryFunc == null || (await this.retryFunc(req, response, attempt))) {
 
-                     const retryAfter = response.headers["retry-after"];
 
-                     let delay = this.#throttle.slotInterval * Math.trunc(Math.random() * Math.pow(2, attempt));
 
-                     if (typeof (retryAfter) === "string" && retryAfter.match(/^[1-9][0-9]*$/)) {
 
-                         delay = parseInt(retryAfter);
 
-                     }
 
-                     return req.clone().#send(attempt + 1, expires, delay, _request, response);
 
-                 }
 
-             }
 
-             if (this.processFunc) {
 
-                 checkSignal(_request.#signal);
 
-                 try {
 
-                     response = await this.processFunc(req, response);
 
-                 }
 
-                 catch (error) {
 
-                     // Something went wrong during processing; throw a 5xx server error
 
-                     if (error.throttle == null || typeof (error.stall) !== "number") {
 
-                         response.makeServerError("error in post-processing function", error).assertOk();
 
-                     }
 
-                     // Throttle
 
-                     let delay = this.#throttle.slotInterval * Math.trunc(Math.random() * Math.pow(2, attempt));
 
-                     if (error.stall >= 0) {
 
-                         delay = error.stall;
 
-                     }
 
-                     return req.clone().#send(attempt + 1, expires, delay, _request, response);
 
-                 }
 
-             }
 
-             return response;
 
-         }
 
-         /**
 
-          *  Resolves to the response by sending the request.
 
-          */
 
-         send() {
 
-             assert(this.#signal == null, "request already sent", "UNSUPPORTED_OPERATION", { operation: "fetchRequest.send" });
 
-             this.#signal = new FetchCancelSignal(this);
 
-             return this.#send(0, getTime$2() + this.timeout, 0, this, new FetchResponse(0, "", {}, null, this));
 
-         }
 
-         /**
 
-          *  Cancels the inflight response, causing a ``CANCELLED``
 
-          *  error to be rejected from the [[send]].
 
-          */
 
-         cancel() {
 
-             assert(this.#signal != null, "request has not been sent", "UNSUPPORTED_OPERATION", { operation: "fetchRequest.cancel" });
 
-             const signal = fetchSignals.get(this);
 
-             if (!signal) {
 
-                 throw new Error("missing signal; should not happen");
 
-             }
 
-             signal();
 
-         }
 
-         /**
 
-          *  Returns a new [[FetchRequest]] that represents the redirection
 
-          *  to %%location%%.
 
-          */
 
-         redirect(location) {
 
-             // Redirection; for now we only support absolute locations
 
-             const current = this.url.split(":")[0].toLowerCase();
 
-             const target = location.split(":")[0].toLowerCase();
 
-             // Don't allow redirecting:
 
-             // - non-GET requests
 
-             // - downgrading the security (e.g. https => http)
 
-             // - to non-HTTP (or non-HTTPS) protocols [this could be relaxed?]
 
-             assert(this.method === "GET" && (current !== "https" || target !== "http") && location.match(/^https?:/), `unsupported redirect`, "UNSUPPORTED_OPERATION", {
 
-                 operation: `redirect(${this.method} ${JSON.stringify(this.url)} => ${JSON.stringify(location)})`
 
-             });
 
-             // Create a copy of this request, with a new URL
 
-             const req = new FetchRequest(location);
 
-             req.method = "GET";
 
-             req.allowGzip = this.allowGzip;
 
-             req.timeout = this.timeout;
 
-             req.#headers = Object.assign({}, this.#headers);
 
-             if (this.#body) {
 
-                 req.#body = new Uint8Array(this.#body);
 
-             }
 
-             req.#bodyType = this.#bodyType;
 
-             // Do not forward credentials unless on the same domain; only absolute
 
-             //req.allowInsecure = false;
 
-             // paths are currently supported; may want a way to specify to forward?
 
-             //setStore(req.#props, "creds", getStore(this.#pros, "creds"));
 
-             return req;
 
-         }
 
-         /**
 
-          *  Create a new copy of this request.
 
-          */
 
-         clone() {
 
-             const clone = new FetchRequest(this.url);
 
-             // Preserve "default method" (i.e. null)
 
-             clone.#method = this.#method;
 
-             // Preserve "default body" with type, copying the Uint8Array is present
 
-             if (this.#body) {
 
-                 clone.#body = this.#body;
 
-             }
 
-             clone.#bodyType = this.#bodyType;
 
-             // Preserve "default headers"
 
-             clone.#headers = Object.assign({}, this.#headers);
 
-             // Credentials is readonly, so we copy internally
 
-             clone.#creds = this.#creds;
 
-             if (this.allowGzip) {
 
-                 clone.allowGzip = true;
 
-             }
 
-             clone.timeout = this.timeout;
 
-             if (this.allowInsecureAuthentication) {
 
-                 clone.allowInsecureAuthentication = true;
 
-             }
 
-             clone.#preflight = this.#preflight;
 
-             clone.#process = this.#process;
 
-             clone.#retry = this.#retry;
 
-             clone.#throttle = Object.assign({}, this.#throttle);
 
-             clone.#getUrlFunc = this.#getUrlFunc;
 
-             return clone;
 
-         }
 
-         /**
 
-          *  Locks all static configuration for gateways and FetchGetUrlFunc
 
-          *  registration.
 
-          */
 
-         static lockConfig() {
 
-             locked$5 = true;
 
-         }
 
-         /**
 
-          *  Get the current Gateway function for %%scheme%%.
 
-          */
 
-         static getGateway(scheme) {
 
-             return Gateways[scheme.toLowerCase()] || null;
 
-         }
 
-         /**
 
-          *  Use the %%func%% when fetching URIs using %%scheme%%.
 
-          *
 
-          *  This method affects all requests globally.
 
-          *
 
-          *  If [[lockConfig]] has been called, no change is made and this
 
-          *  throws.
 
-          */
 
-         static registerGateway(scheme, func) {
 
-             scheme = scheme.toLowerCase();
 
-             if (scheme === "http" || scheme === "https") {
 
-                 throw new Error(`cannot intercept ${scheme}; use registerGetUrl`);
 
-             }
 
-             if (locked$5) {
 
-                 throw new Error("gateways locked");
 
-             }
 
-             Gateways[scheme] = func;
 
-         }
 
-         /**
 
-          *  Use %%getUrl%% when fetching URIs over HTTP and HTTPS requests.
 
-          *
 
-          *  This method affects all requests globally.
 
-          *
 
-          *  If [[lockConfig]] has been called, no change is made and this
 
-          *  throws.
 
-          */
 
-         static registerGetUrl(getUrl) {
 
-             if (locked$5) {
 
-                 throw new Error("gateways locked");
 
-             }
 
-             defaultGetUrlFunc = getUrl;
 
-         }
 
-         /**
 
-          *  Creates a getUrl function that fetches content from HTTP and
 
-          *  HTTPS URLs.
 
-          *
 
-          *  The available %%options%% are dependent on the platform
 
-          *  implementation of the default getUrl function.
 
-          *
 
-          *  This is not generally something that is needed, but is useful
 
-          *  when trying to customize simple behaviour when fetching HTTP
 
-          *  content.
 
-          */
 
-         static createGetUrlFunc(options) {
 
-             return createGetUrl();
 
-         }
 
-         /**
 
-          *  Creates a function that can "fetch" data URIs.
 
-          *
 
-          *  Note that this is automatically done internally to support
 
-          *  data URIs, so it is not necessary to register it.
 
-          *
 
-          *  This is not generally something that is needed, but may
 
-          *  be useful in a wrapper to perfom custom data URI functionality.
 
-          */
 
-         static createDataGateway() {
 
-             return dataGatewayFunc;
 
-         }
 
-         /**
 
-          *  Creates a function that will fetch IPFS (unvalidated) from
 
-          *  a custom gateway baseUrl.
 
-          *
 
-          *  The default IPFS gateway used internally is
 
-          *  ``"https:/\/gateway.ipfs.io/ipfs/"``.
 
-          */
 
-         static createIpfsGatewayFunc(baseUrl) {
 
-             return getIpfsGatewayFunc(baseUrl);
 
-         }
 
-     }
 
-     /**
 
-      *  The response for a FetchRequest.
 
-      */
 
-     class FetchResponse {
 
-         #statusCode;
 
-         #statusMessage;
 
-         #headers;
 
-         #body;
 
-         #request;
 
-         #error;
 
-         toString() {
 
-             return `<FetchResponse status=${this.statusCode} body=${this.#body ? hexlify(this.#body) : "null"}>`;
 
-         }
 
-         /**
 
-          *  The response status code.
 
-          */
 
-         get statusCode() { return this.#statusCode; }
 
-         /**
 
-          *  The response status message.
 
-          */
 
-         get statusMessage() { return this.#statusMessage; }
 
-         /**
 
-          *  The response headers. All keys are lower-case.
 
-          */
 
-         get headers() { return Object.assign({}, this.#headers); }
 
-         /**
 
-          *  The response body, or ``null`` if there was no body.
 
-          */
 
-         get body() {
 
-             return (this.#body == null) ? null : new Uint8Array(this.#body);
 
-         }
 
-         /**
 
-          *  The response body as a UTF-8 encoded string, or the empty
 
-          *  string (i.e. ``""``) if there was no body.
 
-          *
 
-          *  An error is thrown if the body is invalid UTF-8 data.
 
-          */
 
-         get bodyText() {
 
-             try {
 
-                 return (this.#body == null) ? "" : toUtf8String(this.#body);
 
-             }
 
-             catch (error) {
 
-                 assert(false, "response body is not valid UTF-8 data", "UNSUPPORTED_OPERATION", {
 
-                     operation: "bodyText", info: { response: this }
 
-                 });
 
-             }
 
-         }
 
-         /**
 
-          *  The response body, decoded as JSON.
 
-          *
 
-          *  An error is thrown if the body is invalid JSON-encoded data
 
-          *  or if there was no body.
 
-          */
 
-         get bodyJson() {
 
-             try {
 
-                 return JSON.parse(this.bodyText);
 
-             }
 
-             catch (error) {
 
-                 assert(false, "response body is not valid JSON", "UNSUPPORTED_OPERATION", {
 
-                     operation: "bodyJson", info: { response: this }
 
-                 });
 
-             }
 
-         }
 
-         [Symbol.iterator]() {
 
-             const headers = this.headers;
 
-             const keys = Object.keys(headers);
 
-             let index = 0;
 
-             return {
 
-                 next: () => {
 
-                     if (index < keys.length) {
 
-                         const key = keys[index++];
 
-                         return {
 
-                             value: [key, headers[key]], done: false
 
-                         };
 
-                     }
 
-                     return { value: undefined, done: true };
 
-                 }
 
-             };
 
-         }
 
-         constructor(statusCode, statusMessage, headers, body, request) {
 
-             this.#statusCode = statusCode;
 
-             this.#statusMessage = statusMessage;
 
-             this.#headers = Object.keys(headers).reduce((accum, k) => {
 
-                 accum[k.toLowerCase()] = String(headers[k]);
 
-                 return accum;
 
-             }, {});
 
-             this.#body = ((body == null) ? null : new Uint8Array(body));
 
-             this.#request = (request || null);
 
-             this.#error = { message: "" };
 
-         }
 
-         /**
 
-          *  Return a Response with matching headers and body, but with
 
-          *  an error status code (i.e. 599) and %%message%% with an
 
-          *  optional %%error%%.
 
-          */
 
-         makeServerError(message, error) {
 
-             let statusMessage;
 
-             if (!message) {
 
-                 message = `${this.statusCode} ${this.statusMessage}`;
 
-                 statusMessage = `CLIENT ESCALATED SERVER ERROR (${message})`;
 
-             }
 
-             else {
 
-                 statusMessage = `CLIENT ESCALATED SERVER ERROR (${this.statusCode} ${this.statusMessage}; ${message})`;
 
-             }
 
-             const response = new FetchResponse(599, statusMessage, this.headers, this.body, this.#request || undefined);
 
-             response.#error = { message, error };
 
-             return response;
 
-         }
 
-         /**
 
-          *  If called within a [request.processFunc](FetchRequest-processFunc)
 
-          *  call, causes the request to retry as if throttled for %%stall%%
 
-          *  milliseconds.
 
-          */
 
-         throwThrottleError(message, stall) {
 
-             if (stall == null) {
 
-                 stall = -1;
 
-             }
 
-             else {
 
-                 assertArgument(Number.isInteger(stall) && stall >= 0, "invalid stall timeout", "stall", stall);
 
-             }
 
-             const error = new Error(message || "throttling requests");
 
-             defineProperties(error, { stall, throttle: true });
 
-             throw error;
 
-         }
 
-         /**
 
-          *  Get the header value for %%key%%, ignoring case.
 
-          */
 
-         getHeader(key) {
 
-             return this.headers[key.toLowerCase()];
 
-         }
 
-         /**
 
-          *  Returns true if the response has a body.
 
-          */
 
-         hasBody() {
 
-             return (this.#body != null);
 
-         }
 
-         /**
 
-          *  The request made for this response.
 
-          */
 
-         get request() { return this.#request; }
 
-         /**
 
-          *  Returns true if this response was a success statusCode.
 
-          */
 
-         ok() {
 
-             return (this.#error.message === "" && this.statusCode >= 200 && this.statusCode < 300);
 
-         }
 
-         /**
 
-          *  Throws a ``SERVER_ERROR`` if this response is not ok.
 
-          */
 
-         assertOk() {
 
-             if (this.ok()) {
 
-                 return;
 
-             }
 
-             let { message, error } = this.#error;
 
-             if (message === "") {
 
-                 message = `server response ${this.statusCode} ${this.statusMessage}`;
 
-             }
 
-             let requestUrl = null;
 
-             if (this.request) {
 
-                 requestUrl = this.request.url;
 
-             }
 
-             let responseBody = null;
 
-             try {
 
-                 if (this.#body) {
 
-                     responseBody = toUtf8String(this.#body);
 
-                 }
 
-             }
 
-             catch (e) { }
 
-             assert(false, message, "SERVER_ERROR", {
 
-                 request: (this.request || "unknown request"), response: this, error,
 
-                 info: {
 
-                     requestUrl, responseBody,
 
-                     responseStatus: `${this.statusCode} ${this.statusMessage}`
 
-                 }
 
-             });
 
-         }
 
-     }
 
-     function getTime$2() { return (new Date()).getTime(); }
 
-     function unpercent(value) {
 
-         return toUtf8Bytes(value.replace(/%([0-9a-f][0-9a-f])/gi, (all, code) => {
 
-             return String.fromCharCode(parseInt(code, 16));
 
-         }));
 
-     }
 
-     function wait(delay) {
 
-         return new Promise((resolve) => setTimeout(resolve, delay));
 
-     }
 
-     /**
 
-      *  The **FixedNumber** class permits using values with decimal places,
 
-      *  using fixed-pont math.
 
-      *
 
-      *  Fixed-point math is still based on integers under-the-hood, but uses an
 
-      *  internal offset to store fractional components below, and each operation
 
-      *  corrects for this after each operation.
 
-      *
 
-      *  @_section: api/utils/fixed-point-math:Fixed-Point Maths  [about-fixed-point-math]
 
-      */
 
-     const BN_N1 = BigInt(-1);
 
-     const BN_0$8 = BigInt(0);
 
-     const BN_1$4 = BigInt(1);
 
-     const BN_5 = BigInt(5);
 
-     const _guard$5 = {};
 
-     // Constant to pull zeros from for multipliers
 
-     let Zeros$1 = "0000";
 
-     while (Zeros$1.length < 80) {
 
-         Zeros$1 += Zeros$1;
 
-     }
 
-     // Returns a string "1" followed by decimal "0"s
 
-     function getTens(decimals) {
 
-         let result = Zeros$1;
 
-         while (result.length < decimals) {
 
-             result += result;
 
-         }
 
-         return BigInt("1" + result.substring(0, decimals));
 
-     }
 
-     function checkValue(val, format, safeOp) {
 
-         const width = BigInt(format.width);
 
-         if (format.signed) {
 
-             const limit = (BN_1$4 << (width - BN_1$4));
 
-             assert(safeOp == null || (val >= -limit && val < limit), "overflow", "NUMERIC_FAULT", {
 
-                 operation: safeOp, fault: "overflow", value: val
 
-             });
 
-             if (val > BN_0$8) {
 
-                 val = fromTwos(mask(val, width), width);
 
-             }
 
-             else {
 
-                 val = -fromTwos(mask(-val, width), width);
 
-             }
 
-         }
 
-         else {
 
-             const limit = (BN_1$4 << width);
 
-             assert(safeOp == null || (val >= 0 && val < limit), "overflow", "NUMERIC_FAULT", {
 
-                 operation: safeOp, fault: "overflow", value: val
 
-             });
 
-             val = (((val % limit) + limit) % limit) & (limit - BN_1$4);
 
-         }
 
-         return val;
 
-     }
 
-     function getFormat(value) {
 
-         if (typeof (value) === "number") {
 
-             value = `fixed128x${value}`;
 
-         }
 
-         let signed = true;
 
-         let width = 128;
 
-         let decimals = 18;
 
-         if (typeof (value) === "string") {
 
-             // Parse the format string
 
-             if (value === "fixed") ;
 
-             else if (value === "ufixed") {
 
-                 signed = false;
 
-             }
 
-             else {
 
-                 const match = value.match(/^(u?)fixed([0-9]+)x([0-9]+)$/);
 
-                 assertArgument(match, "invalid fixed format", "format", value);
 
-                 signed = (match[1] !== "u");
 
-                 width = parseInt(match[2]);
 
-                 decimals = parseInt(match[3]);
 
-             }
 
-         }
 
-         else if (value) {
 
-             // Extract the values from the object
 
-             const v = value;
 
-             const check = (key, type, defaultValue) => {
 
-                 if (v[key] == null) {
 
-                     return defaultValue;
 
-                 }
 
-                 assertArgument(typeof (v[key]) === type, "invalid fixed format (" + key + " not " + type + ")", "format." + key, v[key]);
 
-                 return v[key];
 
-             };
 
-             signed = check("signed", "boolean", signed);
 
-             width = check("width", "number", width);
 
-             decimals = check("decimals", "number", decimals);
 
-         }
 
-         assertArgument((width % 8) === 0, "invalid FixedNumber width (not byte aligned)", "format.width", width);
 
-         assertArgument(decimals <= 80, "invalid FixedNumber decimals (too large)", "format.decimals", decimals);
 
-         const name = (signed ? "" : "u") + "fixed" + String(width) + "x" + String(decimals);
 
-         return { signed, width, decimals, name };
 
-     }
 
-     function toString(val, decimals) {
 
-         let negative = "";
 
-         if (val < BN_0$8) {
 
-             negative = "-";
 
-             val *= BN_N1;
 
-         }
 
-         let str = val.toString();
 
-         // No decimal point for whole values
 
-         if (decimals === 0) {
 
-             return (negative + str);
 
-         }
 
-         // Pad out to the whole component (including a whole digit)
 
-         while (str.length <= decimals) {
 
-             str = Zeros$1 + str;
 
-         }
 
-         // Insert the decimal point
 
-         const index = str.length - decimals;
 
-         str = str.substring(0, index) + "." + str.substring(index);
 
-         // Trim the whole component (leaving at least one 0)
 
-         while (str[0] === "0" && str[1] !== ".") {
 
-             str = str.substring(1);
 
-         }
 
-         // Trim the decimal component (leaving at least one 0)
 
-         while (str[str.length - 1] === "0" && str[str.length - 2] !== ".") {
 
-             str = str.substring(0, str.length - 1);
 
-         }
 
-         return (negative + str);
 
-     }
 
-     /**
 
-      *  A FixedNumber represents a value over its [[FixedFormat]]
 
-      *  arithmetic field.
 
-      *
 
-      *  A FixedNumber can be used to perform math, losslessly, on
 
-      *  values which have decmial places.
 
-      *
 
-      *  A FixedNumber has a fixed bit-width to store values in, and stores all
 
-      *  values internally by multiplying the value by 10 raised to the power of
 
-      *  %%decimals%%.
 
-      *
 
-      *  If operations are performed that cause a value to grow too high (close to
 
-      *  positive infinity) or too low (close to negative infinity), the value
 
-      *  is said to //overflow//.
 
-      *
 
-      *  For example, an 8-bit signed value, with 0 decimals may only be within
 
-      *  the range ``-128`` to ``127``; so ``-128 - 1`` will overflow and become
 
-      *  ``127``. Likewise, ``127 + 1`` will overflow and become ``-127``.
 
-      *
 
-      *  Many operation have a normal and //unsafe// variant. The normal variant
 
-      *  will throw a [[NumericFaultError]] on any overflow, while the //unsafe//
 
-      *  variant will silently allow overflow, corrupting its value value.
 
-      *
 
-      *  If operations are performed that cause a value to become too small
 
-      *  (close to zero), the value loses precison and is said to //underflow//.
 
-      *
 
-      *  For example, an value with 1 decimal place may store a number as small
 
-      *  as ``0.1``, but the value of ``0.1 / 2`` is ``0.05``, which cannot fit
 
-      *  into 1 decimal place, so underflow occurs which means precision is lost
 
-      *  and the value becomes ``0``.
 
-      *
 
-      *  Some operations have a normal and //signalling// variant. The normal
 
-      *  variant will silently ignore underflow, while the //signalling// variant
 
-      *  will thow a [[NumericFaultError]] on underflow.
 
-      */
 
-     class FixedNumber {
 
-         /**
 
-          *  The specific fixed-point arithmetic field for this value.
 
-          */
 
-         format;
 
-         #format;
 
-         // The actual value (accounting for decimals)
 
-         #val;
 
-         // A base-10 value to multiple values by to maintain the magnitude
 
-         #tens;
 
-         /**
 
-          *  This is a property so console.log shows a human-meaningful value.
 
-          *
 
-          *  @private
 
-          */
 
-         _value;
 
-         // Use this when changing this file to get some typing info,
 
-         // but then switch to any to mask the internal type
 
-         //constructor(guard: any, value: bigint, format: _FixedFormat) {
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, value, format) {
 
-             assertPrivate(guard, _guard$5, "FixedNumber");
 
-             this.#val = value;
 
-             this.#format = format;
 
-             const _value = toString(value, format.decimals);
 
-             defineProperties(this, { format: format.name, _value });
 
-             this.#tens = getTens(format.decimals);
 
-         }
 
-         /**
 
-          *  If true, negative values are permitted, otherwise only
 
-          *  positive values and zero are allowed.
 
-          */
 
-         get signed() { return this.#format.signed; }
 
-         /**
 
-          *  The number of bits available to store the value.
 
-          */
 
-         get width() { return this.#format.width; }
 
-         /**
 
-          *  The number of decimal places in the fixed-point arithment field.
 
-          */
 
-         get decimals() { return this.#format.decimals; }
 
-         /**
 
-          *  The value as an integer, based on the smallest unit the
 
-          *  [[decimals]] allow.
 
-          */
 
-         get value() { return this.#val; }
 
-         #checkFormat(other) {
 
-             assertArgument(this.format === other.format, "incompatible format; use fixedNumber.toFormat", "other", other);
 
-         }
 
-         #checkValue(val, safeOp) {
 
-             /*
 
-                     const width = BigInt(this.width);
 
-                     if (this.signed) {
 
-                         const limit = (BN_1 << (width - BN_1));
 
-                         assert(safeOp == null || (val >= -limit  && val < limit), "overflow", "NUMERIC_FAULT", {
 
-                             operation: <string>safeOp, fault: "overflow", value: val
 
-                         });
 
-             
 
-                         if (val > BN_0) {
 
-                             val = fromTwos(mask(val, width), width);
 
-                         } else {
 
-                             val = -fromTwos(mask(-val, width), width);
 
-                         }
 
-             
 
-                     } else {
 
-                         const masked = mask(val, width);
 
-                         assert(safeOp == null || (val >= 0 && val === masked), "overflow", "NUMERIC_FAULT", {
 
-                             operation: <string>safeOp, fault: "overflow", value: val
 
-                         });
 
-                         val = masked;
 
-                     }
 
-             */
 
-             val = checkValue(val, this.#format, safeOp);
 
-             return new FixedNumber(_guard$5, val, this.#format);
 
-         }
 
-         #add(o, safeOp) {
 
-             this.#checkFormat(o);
 
-             return this.#checkValue(this.#val + o.#val, safeOp);
 
-         }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% added
 
-          *  to %%other%%, ignoring overflow.
 
-          */
 
-         addUnsafe(other) { return this.#add(other); }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% added
 
-          *  to %%other%%. A [[NumericFaultError]] is thrown if overflow
 
-          *  occurs.
 
-          */
 
-         add(other) { return this.#add(other, "add"); }
 
-         #sub(o, safeOp) {
 
-             this.#checkFormat(o);
 
-             return this.#checkValue(this.#val - o.#val, safeOp);
 
-         }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%other%% subtracted
 
-          *  from %%this%%, ignoring overflow.
 
-          */
 
-         subUnsafe(other) { return this.#sub(other); }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%other%% subtracted
 
-          *  from %%this%%. A [[NumericFaultError]] is thrown if overflow
 
-          *  occurs.
 
-          */
 
-         sub(other) { return this.#sub(other, "sub"); }
 
-         #mul(o, safeOp) {
 
-             this.#checkFormat(o);
 
-             return this.#checkValue((this.#val * o.#val) / this.#tens, safeOp);
 
-         }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% multiplied
 
-          *  by %%other%%, ignoring overflow and underflow (precision loss).
 
-          */
 
-         mulUnsafe(other) { return this.#mul(other); }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% multiplied
 
-          *  by %%other%%. A [[NumericFaultError]] is thrown if overflow
 
-          *  occurs.
 
-          */
 
-         mul(other) { return this.#mul(other, "mul"); }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% multiplied
 
-          *  by %%other%%. A [[NumericFaultError]] is thrown if overflow
 
-          *  occurs or if underflow (precision loss) occurs.
 
-          */
 
-         mulSignal(other) {
 
-             this.#checkFormat(other);
 
-             const value = this.#val * other.#val;
 
-             assert((value % this.#tens) === BN_0$8, "precision lost during signalling mul", "NUMERIC_FAULT", {
 
-                 operation: "mulSignal", fault: "underflow", value: this
 
-             });
 
-             return this.#checkValue(value / this.#tens, "mulSignal");
 
-         }
 
-         #div(o, safeOp) {
 
-             assert(o.#val !== BN_0$8, "division by zero", "NUMERIC_FAULT", {
 
-                 operation: "div", fault: "divide-by-zero", value: this
 
-             });
 
-             this.#checkFormat(o);
 
-             return this.#checkValue((this.#val * this.#tens) / o.#val, safeOp);
 
-         }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% divided
 
-          *  by %%other%%, ignoring underflow (precision loss). A
 
-          *  [[NumericFaultError]] is thrown if overflow occurs.
 
-          */
 
-         divUnsafe(other) { return this.#div(other); }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% divided
 
-          *  by %%other%%, ignoring underflow (precision loss). A
 
-          *  [[NumericFaultError]] is thrown if overflow occurs.
 
-          */
 
-         div(other) { return this.#div(other, "div"); }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the result of %%this%% divided
 
-          *  by %%other%%. A [[NumericFaultError]] is thrown if underflow
 
-          *  (precision loss) occurs.
 
-          */
 
-         divSignal(other) {
 
-             assert(other.#val !== BN_0$8, "division by zero", "NUMERIC_FAULT", {
 
-                 operation: "div", fault: "divide-by-zero", value: this
 
-             });
 
-             this.#checkFormat(other);
 
-             const value = (this.#val * this.#tens);
 
-             assert((value % other.#val) === BN_0$8, "precision lost during signalling div", "NUMERIC_FAULT", {
 
-                 operation: "divSignal", fault: "underflow", value: this
 
-             });
 
-             return this.#checkValue(value / other.#val, "divSignal");
 
-         }
 
-         /**
 
-          *  Returns a comparison result between %%this%% and %%other%%.
 
-          *
 
-          *  This is suitable for use in sorting, where ``-1`` implies %%this%%
 
-          *  is smaller, ``1`` implies %%this%% is larger and ``0`` implies
 
-          *  both are equal.
 
-          */
 
-         cmp(other) {
 
-             let a = this.value, b = other.value;
 
-             // Coerce a and b to the same magnitude
 
-             const delta = this.decimals - other.decimals;
 
-             if (delta > 0) {
 
-                 b *= getTens(delta);
 
-             }
 
-             else if (delta < 0) {
 
-                 a *= getTens(-delta);
 
-             }
 
-             // Comnpare
 
-             if (a < b) {
 
-                 return -1;
 
-             }
 
-             if (a > b) {
 
-                 return 1;
 
-             }
 
-             return 0;
 
-         }
 
-         /**
 
-          *  Returns true if %%other%% is equal to %%this%%.
 
-          */
 
-         eq(other) { return this.cmp(other) === 0; }
 
-         /**
 
-          *  Returns true if %%other%% is less than to %%this%%.
 
-          */
 
-         lt(other) { return this.cmp(other) < 0; }
 
-         /**
 
-          *  Returns true if %%other%% is less than or equal to %%this%%.
 
-          */
 
-         lte(other) { return this.cmp(other) <= 0; }
 
-         /**
 
-          *  Returns true if %%other%% is greater than to %%this%%.
 
-          */
 
-         gt(other) { return this.cmp(other) > 0; }
 
-         /**
 
-          *  Returns true if %%other%% is greater than or equal to %%this%%.
 
-          */
 
-         gte(other) { return this.cmp(other) >= 0; }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] which is the largest **integer**
 
-          *  that is less than or equal to %%this%%.
 
-          *
 
-          *  The decimal component of the result will always be ``0``.
 
-          */
 
-         floor() {
 
-             let val = this.#val;
 
-             if (this.#val < BN_0$8) {
 
-                 val -= this.#tens - BN_1$4;
 
-             }
 
-             val = (this.#val / this.#tens) * this.#tens;
 
-             return this.#checkValue(val, "floor");
 
-         }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] which is the smallest **integer**
 
-          *  that is greater than or equal to %%this%%.
 
-          *
 
-          *  The decimal component of the result will always be ``0``.
 
-          */
 
-         ceiling() {
 
-             let val = this.#val;
 
-             if (this.#val > BN_0$8) {
 
-                 val += this.#tens - BN_1$4;
 
-             }
 
-             val = (this.#val / this.#tens) * this.#tens;
 
-             return this.#checkValue(val, "ceiling");
 
-         }
 
-         /**
 
-          *  Returns a new [[FixedNumber]] with the decimal component
 
-          *  rounded up on ties at %%decimals%% places.
 
-          */
 
-         round(decimals) {
 
-             if (decimals == null) {
 
-                 decimals = 0;
 
-             }
 
-             // Not enough precision to not already be rounded
 
-             if (decimals >= this.decimals) {
 
-                 return this;
 
-             }
 
-             const delta = this.decimals - decimals;
 
-             const bump = BN_5 * getTens(delta - 1);
 
-             let value = this.value + bump;
 
-             const tens = getTens(delta);
 
-             value = (value / tens) * tens;
 
-             checkValue(value, this.#format, "round");
 
-             return new FixedNumber(_guard$5, value, this.#format);
 
-         }
 
-         /**
 
-          *  Returns true if %%this%% is equal to ``0``.
 
-          */
 
-         isZero() { return (this.#val === BN_0$8); }
 
-         /**
 
-          *  Returns true if %%this%% is less than ``0``.
 
-          */
 
-         isNegative() { return (this.#val < BN_0$8); }
 
-         /**
 
-          *  Returns the string representation of %%this%%.
 
-          */
 
-         toString() { return this._value; }
 
-         /**
 
-          *  Returns a float approximation.
 
-          *
 
-          *  Due to IEEE 754 precission (or lack thereof), this function
 
-          *  can only return an approximation and most values will contain
 
-          *  rounding errors.
 
-          */
 
-         toUnsafeFloat() { return parseFloat(this.toString()); }
 
-         /**
 
-          *  Return a new [[FixedNumber]] with the same value but has had
 
-          *  its field set to %%format%%.
 
-          *
 
-          *  This will throw if the value cannot fit into %%format%%.
 
-          */
 
-         toFormat(format) {
 
-             return FixedNumber.fromString(this.toString(), format);
 
-         }
 
-         /**
 
-          *  Creates a new [[FixedNumber]] for %%value%% divided by
 
-          *  %%decimal%% places with %%format%%.
 
-          *
 
-          *  This will throw a [[NumericFaultError]] if %%value%% (once adjusted
 
-          *  for %%decimals%%) cannot fit in %%format%%, either due to overflow
 
-          *  or underflow (precision loss).
 
-          */
 
-         static fromValue(_value, _decimals, _format) {
 
-             const decimals = (_decimals == null) ? 0 : getNumber(_decimals);
 
-             const format = getFormat(_format);
 
-             let value = getBigInt(_value, "value");
 
-             const delta = decimals - format.decimals;
 
-             if (delta > 0) {
 
-                 const tens = getTens(delta);
 
-                 assert((value % tens) === BN_0$8, "value loses precision for format", "NUMERIC_FAULT", {
 
-                     operation: "fromValue", fault: "underflow", value: _value
 
-                 });
 
-                 value /= tens;
 
-             }
 
-             else if (delta < 0) {
 
-                 value *= getTens(-delta);
 
-             }
 
-             checkValue(value, format, "fromValue");
 
-             return new FixedNumber(_guard$5, value, format);
 
-         }
 
-         /**
 
-          *  Creates a new [[FixedNumber]] for %%value%% with %%format%%.
 
-          *
 
-          *  This will throw a [[NumericFaultError]] if %%value%% cannot fit
 
-          *  in %%format%%, either due to overflow or underflow (precision loss).
 
-          */
 
-         static fromString(_value, _format) {
 
-             const match = _value.match(/^(-?)([0-9]*)\.?([0-9]*)$/);
 
-             assertArgument(match && (match[2].length + match[3].length) > 0, "invalid FixedNumber string value", "value", _value);
 
-             const format = getFormat(_format);
 
-             let whole = (match[2] || "0"), decimal = (match[3] || "");
 
-             // Pad out the decimals
 
-             while (decimal.length < format.decimals) {
 
-                 decimal += Zeros$1;
 
-             }
 
-             // Check precision is safe
 
-             assert(decimal.substring(format.decimals).match(/^0*$/), "too many decimals for format", "NUMERIC_FAULT", {
 
-                 operation: "fromString", fault: "underflow", value: _value
 
-             });
 
-             // Remove extra padding
 
-             decimal = decimal.substring(0, format.decimals);
 
-             const value = BigInt(match[1] + whole + decimal);
 
-             checkValue(value, format, "fromString");
 
-             return new FixedNumber(_guard$5, value, format);
 
-         }
 
-         /**
 
-          *  Creates a new [[FixedNumber]] with the big-endian representation
 
-          *  %%value%% with %%format%%.
 
-          *
 
-          *  This will throw a [[NumericFaultError]] if %%value%% cannot fit
 
-          *  in %%format%% due to overflow.
 
-          */
 
-         static fromBytes(_value, _format) {
 
-             let value = toBigInt(getBytes(_value, "value"));
 
-             const format = getFormat(_format);
 
-             if (format.signed) {
 
-                 value = fromTwos(value, format.width);
 
-             }
 
-             checkValue(value, format, "fromBytes");
 
-             return new FixedNumber(_guard$5, value, format);
 
-         }
 
-     }
 
-     //const f1 = FixedNumber.fromString("12.56", "fixed16x2");
 
-     //const f2 = FixedNumber.fromString("0.3", "fixed16x2");
 
-     //console.log(f1.divSignal(f2));
 
-     //const BUMP = FixedNumber.from("0.5");
 
-     //See: https://github.com/ethereum/wiki/wiki/RLP
 
-     function hexlifyByte(value) {
 
-         let result = value.toString(16);
 
-         while (result.length < 2) {
 
-             result = "0" + result;
 
-         }
 
-         return "0x" + result;
 
-     }
 
-     function unarrayifyInteger(data, offset, length) {
 
-         let result = 0;
 
-         for (let i = 0; i < length; i++) {
 
-             result = (result * 256) + data[offset + i];
 
-         }
 
-         return result;
 
-     }
 
-     function _decodeChildren(data, offset, childOffset, length) {
 
-         const result = [];
 
-         while (childOffset < offset + 1 + length) {
 
-             const decoded = _decode(data, childOffset);
 
-             result.push(decoded.result);
 
-             childOffset += decoded.consumed;
 
-             assert(childOffset <= offset + 1 + length, "child data too short", "BUFFER_OVERRUN", {
 
-                 buffer: data, length, offset
 
-             });
 
-         }
 
-         return { consumed: (1 + length), result: result };
 
-     }
 
-     // returns { consumed: number, result: Object }
 
-     function _decode(data, offset) {
 
-         assert(data.length !== 0, "data too short", "BUFFER_OVERRUN", {
 
-             buffer: data, length: 0, offset: 1
 
-         });
 
-         const checkOffset = (offset) => {
 
-             assert(offset <= data.length, "data short segment too short", "BUFFER_OVERRUN", {
 
-                 buffer: data, length: data.length, offset
 
-             });
 
-         };
 
-         // Array with extra length prefix
 
-         if (data[offset] >= 0xf8) {
 
-             const lengthLength = data[offset] - 0xf7;
 
-             checkOffset(offset + 1 + lengthLength);
 
-             const length = unarrayifyInteger(data, offset + 1, lengthLength);
 
-             checkOffset(offset + 1 + lengthLength + length);
 
-             return _decodeChildren(data, offset, offset + 1 + lengthLength, lengthLength + length);
 
-         }
 
-         else if (data[offset] >= 0xc0) {
 
-             const length = data[offset] - 0xc0;
 
-             checkOffset(offset + 1 + length);
 
-             return _decodeChildren(data, offset, offset + 1, length);
 
-         }
 
-         else if (data[offset] >= 0xb8) {
 
-             const lengthLength = data[offset] - 0xb7;
 
-             checkOffset(offset + 1 + lengthLength);
 
-             const length = unarrayifyInteger(data, offset + 1, lengthLength);
 
-             checkOffset(offset + 1 + lengthLength + length);
 
-             const result = hexlify(data.slice(offset + 1 + lengthLength, offset + 1 + lengthLength + length));
 
-             return { consumed: (1 + lengthLength + length), result: result };
 
-         }
 
-         else if (data[offset] >= 0x80) {
 
-             const length = data[offset] - 0x80;
 
-             checkOffset(offset + 1 + length);
 
-             const result = hexlify(data.slice(offset + 1, offset + 1 + length));
 
-             return { consumed: (1 + length), result: result };
 
-         }
 
-         return { consumed: 1, result: hexlifyByte(data[offset]) };
 
-     }
 
-     /**
 
-      *  Decodes %%data%% into the structured data it represents.
 
-      */
 
-     function decodeRlp(_data) {
 
-         const data = getBytes(_data, "data");
 
-         const decoded = _decode(data, 0);
 
-         assertArgument(decoded.consumed === data.length, "unexpected junk after rlp payload", "data", _data);
 
-         return decoded.result;
 
-     }
 
-     //See: https://github.com/ethereum/wiki/wiki/RLP
 
-     function arrayifyInteger(value) {
 
-         const result = [];
 
-         while (value) {
 
-             result.unshift(value & 0xff);
 
-             value >>= 8;
 
-         }
 
-         return result;
 
-     }
 
-     function _encode(object) {
 
-         if (Array.isArray(object)) {
 
-             let payload = [];
 
-             object.forEach(function (child) {
 
-                 payload = payload.concat(_encode(child));
 
-             });
 
-             if (payload.length <= 55) {
 
-                 payload.unshift(0xc0 + payload.length);
 
-                 return payload;
 
-             }
 
-             const length = arrayifyInteger(payload.length);
 
-             length.unshift(0xf7 + length.length);
 
-             return length.concat(payload);
 
-         }
 
-         const data = Array.prototype.slice.call(getBytes(object, "object"));
 
-         if (data.length === 1 && data[0] <= 0x7f) {
 
-             return data;
 
-         }
 
-         else if (data.length <= 55) {
 
-             data.unshift(0x80 + data.length);
 
-             return data;
 
-         }
 
-         const length = arrayifyInteger(data.length);
 
-         length.unshift(0xb7 + length.length);
 
-         return length.concat(data);
 
-     }
 
-     const nibbles = "0123456789abcdef";
 
-     /**
 
-      *  Encodes %%object%% as an RLP-encoded [[DataHexString]].
 
-      */
 
-     function encodeRlp(object) {
 
-         let result = "0x";
 
-         for (const v of _encode(object)) {
 
-             result += nibbles[v >> 4];
 
-             result += nibbles[v & 0xf];
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  Most interactions with Ethereum requires integer values, which use
 
-      *  the smallest magnitude unit.
 
-      *
 
-      *  For example, imagine dealing with dollars and cents. Since dollars
 
-      *  are divisible, non-integer values are possible, such as ``$10.77``.
 
-      *  By using the smallest indivisible unit (i.e. cents), the value can
 
-      *  be kept as the integer ``1077``.
 
-      *
 
-      *  When receiving decimal input from the user (as a decimal string),
 
-      *  the value should be converted to an integer and when showing a user
 
-      *  a value, the integer value should be converted to a decimal string.
 
-      *
 
-      *  This creates a clear distinction, between values to be used by code
 
-      *  (integers) and values used for display logic to users (decimals).
 
-      *
 
-      *  The native unit in Ethereum, //ether// is divisible to 18 decimal places,
 
-      *  where each individual unit is called a //wei//.
 
-      *
 
-      *  @_subsection api/utils:Unit Conversion  [about-units]
 
-      */
 
-     const names = [
 
-         "wei",
 
-         "kwei",
 
-         "mwei",
 
-         "gwei",
 
-         "szabo",
 
-         "finney",
 
-         "ether",
 
-     ];
 
-     /**
 
-      *  Converts %%value%% into a //decimal string//, assuming %%unit%% decimal
 
-      *  places. The %%unit%% may be the number of decimal places or the name of
 
-      *  a unit (e.g. ``"gwei"`` for 9 decimal places).
 
-      *
 
-      */
 
-     function formatUnits(value, unit) {
 
-         let decimals = 18;
 
-         if (typeof (unit) === "string") {
 
-             const index = names.indexOf(unit);
 
-             assertArgument(index >= 0, "invalid unit", "unit", unit);
 
-             decimals = 3 * index;
 
-         }
 
-         else if (unit != null) {
 
-             decimals = getNumber(unit, "unit");
 
-         }
 
-         return FixedNumber.fromValue(value, decimals, { decimals, width: 512 }).toString();
 
-     }
 
-     /**
 
-      *  Converts the //decimal string// %%value%% to a BigInt, assuming
 
-      *  %%unit%% decimal places. The %%unit%% may the number of decimal places
 
-      *  or the name of a unit (e.g. ``"gwei"`` for 9 decimal places).
 
-      */
 
-     function parseUnits$1(value, unit) {
 
-         assertArgument(typeof (value) === "string", "value must be a string", "value", value);
 
-         let decimals = 18;
 
-         if (typeof (unit) === "string") {
 
-             const index = names.indexOf(unit);
 
-             assertArgument(index >= 0, "invalid unit", "unit", unit);
 
-             decimals = 3 * index;
 
-         }
 
-         else if (unit != null) {
 
-             decimals = getNumber(unit, "unit");
 
-         }
 
-         return FixedNumber.fromString(value, { decimals, width: 512 }).value;
 
-     }
 
-     /**
 
-      *  Converts %%value%% into a //decimal string// using 18 decimal places.
 
-      */
 
-     function formatEther(wei) {
 
-         return formatUnits(wei, 18);
 
-     }
 
-     /**
 
-      *  Converts the //decimal string// %%ether%% to a BigInt, using 18
 
-      *  decimal places.
 
-      */
 
-     function parseEther(ether) {
 
-         return parseUnits$1(ether, 18);
 
-     }
 
-     /**
 
-      *  Explain UUID and link to RFC here.
 
-      *
 
-      *  @_subsection: api/utils:UUID  [about-uuid]
 
-      */
 
-     /**
 
-      *  Returns the version 4 [[link-uuid]] for the %%randomBytes%%.
 
-      *
 
-      *  @see: https://www.ietf.org/rfc/rfc4122.txt (Section 4.4)
 
-      */
 
-     function uuidV4(randomBytes) {
 
-         const bytes = getBytes(randomBytes, "randomBytes");
 
-         // Section: 4.1.3:
 
-         // - time_hi_and_version[12:16] = 0b0100
 
-         bytes[6] = (bytes[6] & 0x0f) | 0x40;
 
-         // Section 4.4
 
-         // - clock_seq_hi_and_reserved[6] = 0b0
 
-         // - clock_seq_hi_and_reserved[7] = 0b1
 
-         bytes[8] = (bytes[8] & 0x3f) | 0x80;
 
-         const value = hexlify(bytes);
 
-         return [
 
-             value.substring(2, 10),
 
-             value.substring(10, 14),
 
-             value.substring(14, 18),
 
-             value.substring(18, 22),
 
-             value.substring(22, 34),
 
-         ].join("-");
 
-     }
 
-     /**
 
-      * @_ignore:
 
-      */
 
-     const WordSize = 32;
 
-     const Padding = new Uint8Array(WordSize);
 
-     // Properties used to immediate pass through to the underlying object
 
-     // - `then` is used to detect if an object is a Promise for await
 
-     const passProperties$1 = ["then"];
 
-     const _guard$4 = {};
 
-     const resultNames = new WeakMap();
 
-     function getNames(result) {
 
-         return resultNames.get(result);
 
-     }
 
-     function setNames(result, names) {
 
-         resultNames.set(result, names);
 
-     }
 
-     function throwError(name, error) {
 
-         const wrapped = new Error(`deferred error during ABI decoding triggered accessing ${name}`);
 
-         wrapped.error = error;
 
-         throw wrapped;
 
-     }
 
-     function toObject(names, items, deep) {
 
-         if (names.indexOf(null) >= 0) {
 
-             return items.map((item, index) => {
 
-                 if (item instanceof Result) {
 
-                     return toObject(getNames(item), item, deep);
 
-                 }
 
-                 return item;
 
-             });
 
-         }
 
-         return names.reduce((accum, name, index) => {
 
-             let item = items.getValue(name);
 
-             if (!(name in accum)) {
 
-                 if (deep && item instanceof Result) {
 
-                     item = toObject(getNames(item), item, deep);
 
-                 }
 
-                 accum[name] = item;
 
-             }
 
-             return accum;
 
-         }, {});
 
-     }
 
-     /**
 
-      *  A [[Result]] is a sub-class of Array, which allows accessing any
 
-      *  of its values either positionally by its index or, if keys are
 
-      *  provided by its name.
 
-      *
 
-      *  @_docloc: api/abi
 
-      */
 
-     class Result extends Array {
 
-         // No longer used; but cannot be removed as it will remove the
 
-         // #private field from the .d.ts which may break backwards
 
-         // compatibility
 
-         #names;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(...args) {
 
-             // To properly sub-class Array so the other built-in
 
-             // functions work, the constructor has to behave fairly
 
-             // well. So, in the event we are created via fromItems()
 
-             // we build the read-only Result object we want, but on
 
-             // any other input, we use the default constructor
 
-             // constructor(guard: any, items: Array<any>, keys?: Array<null | string>);
 
-             const guard = args[0];
 
-             let items = args[1];
 
-             let names = (args[2] || []).slice();
 
-             let wrap = true;
 
-             if (guard !== _guard$4) {
 
-                 items = args;
 
-                 names = [];
 
-                 wrap = false;
 
-             }
 
-             // Can't just pass in ...items since an array of length 1
 
-             // is a special case in the super.
 
-             super(items.length);
 
-             items.forEach((item, index) => { this[index] = item; });
 
-             // Find all unique keys
 
-             const nameCounts = names.reduce((accum, name) => {
 
-                 if (typeof (name) === "string") {
 
-                     accum.set(name, (accum.get(name) || 0) + 1);
 
-                 }
 
-                 return accum;
 
-             }, (new Map()));
 
-             // Remove any key thats not unique
 
-             setNames(this, Object.freeze(items.map((item, index) => {
 
-                 const name = names[index];
 
-                 if (name != null && nameCounts.get(name) === 1) {
 
-                     return name;
 
-                 }
 
-                 return null;
 
-             })));
 
-             // Dummy operations to prevent TypeScript from complaining
 
-             this.#names = [];
 
-             if (this.#names == null) {
 
-                 void (this.#names);
 
-             }
 
-             if (!wrap) {
 
-                 return;
 
-             }
 
-             // A wrapped Result is immutable
 
-             Object.freeze(this);
 
-             // Proxy indices and names so we can trap deferred errors
 
-             const proxy = new Proxy(this, {
 
-                 get: (target, prop, receiver) => {
 
-                     if (typeof (prop) === "string") {
 
-                         // Index accessor
 
-                         if (prop.match(/^[0-9]+$/)) {
 
-                             const index = getNumber(prop, "%index");
 
-                             if (index < 0 || index >= this.length) {
 
-                                 throw new RangeError("out of result range");
 
-                             }
 
-                             const item = target[index];
 
-                             if (item instanceof Error) {
 
-                                 throwError(`index ${index}`, item);
 
-                             }
 
-                             return item;
 
-                         }
 
-                         // Pass important checks (like `then` for Promise) through
 
-                         if (passProperties$1.indexOf(prop) >= 0) {
 
-                             return Reflect.get(target, prop, receiver);
 
-                         }
 
-                         const value = target[prop];
 
-                         if (value instanceof Function) {
 
-                             // Make sure functions work with private variables
 
-                             // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#no_private_property_forwarding
 
-                             return function (...args) {
 
-                                 return value.apply((this === receiver) ? target : this, args);
 
-                             };
 
-                         }
 
-                         else if (!(prop in target)) {
 
-                             // Possible name accessor
 
-                             return target.getValue.apply((this === receiver) ? target : this, [prop]);
 
-                         }
 
-                     }
 
-                     return Reflect.get(target, prop, receiver);
 
-                 }
 
-             });
 
-             setNames(proxy, getNames(this));
 
-             return proxy;
 
-         }
 
-         /**
 
-          *  Returns the Result as a normal Array. If %%deep%%, any children
 
-          *  which are Result objects are also converted to a normal Array.
 
-          *
 
-          *  This will throw if there are any outstanding deferred
 
-          *  errors.
 
-          */
 
-         toArray(deep) {
 
-             const result = [];
 
-             this.forEach((item, index) => {
 
-                 if (item instanceof Error) {
 
-                     throwError(`index ${index}`, item);
 
-                 }
 
-                 if (deep && item instanceof Result) {
 
-                     item = item.toArray(deep);
 
-                 }
 
-                 result.push(item);
 
-             });
 
-             return result;
 
-         }
 
-         /**
 
-          *  Returns the Result as an Object with each name-value pair. If
 
-          *  %%deep%%, any children which are Result objects are also
 
-          *  converted to an Object.
 
-          *
 
-          *  This will throw if any value is unnamed, or if there are
 
-          *  any outstanding deferred errors.
 
-          */
 
-         toObject(deep) {
 
-             const names = getNames(this);
 
-             return names.reduce((accum, name, index) => {
 
-                 assert(name != null, `value at index ${index} unnamed`, "UNSUPPORTED_OPERATION", {
 
-                     operation: "toObject()"
 
-                 });
 
-                 return toObject(names, this, deep);
 
-             }, {});
 
-         }
 
-         /**
 
-          *  @_ignore
 
-          */
 
-         slice(start, end) {
 
-             if (start == null) {
 
-                 start = 0;
 
-             }
 
-             if (start < 0) {
 
-                 start += this.length;
 
-                 if (start < 0) {
 
-                     start = 0;
 
-                 }
 
-             }
 
-             if (end == null) {
 
-                 end = this.length;
 
-             }
 
-             if (end < 0) {
 
-                 end += this.length;
 
-                 if (end < 0) {
 
-                     end = 0;
 
-                 }
 
-             }
 
-             if (end > this.length) {
 
-                 end = this.length;
 
-             }
 
-             const _names = getNames(this);
 
-             const result = [], names = [];
 
-             for (let i = start; i < end; i++) {
 
-                 result.push(this[i]);
 
-                 names.push(_names[i]);
 
-             }
 
-             return new Result(_guard$4, result, names);
 
-         }
 
-         /**
 
-          *  @_ignore
 
-          */
 
-         filter(callback, thisArg) {
 
-             const _names = getNames(this);
 
-             const result = [], names = [];
 
-             for (let i = 0; i < this.length; i++) {
 
-                 const item = this[i];
 
-                 if (item instanceof Error) {
 
-                     throwError(`index ${i}`, item);
 
-                 }
 
-                 if (callback.call(thisArg, item, i, this)) {
 
-                     result.push(item);
 
-                     names.push(_names[i]);
 
-                 }
 
-             }
 
-             return new Result(_guard$4, result, names);
 
-         }
 
-         /**
 
-          *  @_ignore
 
-          */
 
-         map(callback, thisArg) {
 
-             const result = [];
 
-             for (let i = 0; i < this.length; i++) {
 
-                 const item = this[i];
 
-                 if (item instanceof Error) {
 
-                     throwError(`index ${i}`, item);
 
-                 }
 
-                 result.push(callback.call(thisArg, item, i, this));
 
-             }
 
-             return result;
 
-         }
 
-         /**
 
-          *  Returns the value for %%name%%.
 
-          *
 
-          *  Since it is possible to have a key whose name conflicts with
 
-          *  a method on a [[Result]] or its superclass Array, or any
 
-          *  JavaScript keyword, this ensures all named values are still
 
-          *  accessible by name.
 
-          */
 
-         getValue(name) {
 
-             const index = getNames(this).indexOf(name);
 
-             if (index === -1) {
 
-                 return undefined;
 
-             }
 
-             const value = this[index];
 
-             if (value instanceof Error) {
 
-                 throwError(`property ${JSON.stringify(name)}`, value.error);
 
-             }
 
-             return value;
 
-         }
 
-         /**
 
-          *  Creates a new [[Result]] for %%items%% with each entry
 
-          *  also accessible by its corresponding name in %%keys%%.
 
-          */
 
-         static fromItems(items, keys) {
 
-             return new Result(_guard$4, items, keys);
 
-         }
 
-     }
 
-     /**
 
-      *  Returns all errors found in a [[Result]].
 
-      *
 
-      *  Since certain errors encountered when creating a [[Result]] do
 
-      *  not impact the ability to continue parsing data, they are
 
-      *  deferred until they are actually accessed. Hence a faulty string
 
-      *  in an Event that is never used does not impact the program flow.
 
-      *
 
-      *  However, sometimes it may be useful to access, identify or
 
-      *  validate correctness of a [[Result]].
 
-      *
 
-      *  @_docloc api/abi
 
-      */
 
-     function checkResultErrors(result) {
 
-         // Find the first error (if any)
 
-         const errors = [];
 
-         const checkErrors = function (path, object) {
 
-             if (!Array.isArray(object)) {
 
-                 return;
 
-             }
 
-             for (let key in object) {
 
-                 const childPath = path.slice();
 
-                 childPath.push(key);
 
-                 try {
 
-                     checkErrors(childPath, object[key]);
 
-                 }
 
-                 catch (error) {
 
-                     errors.push({ path: childPath, error: error });
 
-                 }
 
-             }
 
-         };
 
-         checkErrors([], result);
 
-         return errors;
 
-     }
 
-     function getValue$1(value) {
 
-         let bytes = toBeArray(value);
 
-         assert(bytes.length <= WordSize, "value out-of-bounds", "BUFFER_OVERRUN", { buffer: bytes, length: WordSize, offset: bytes.length });
 
-         if (bytes.length !== WordSize) {
 
-             bytes = getBytesCopy(concat([Padding.slice(bytes.length % WordSize), bytes]));
 
-         }
 
-         return bytes;
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class Coder {
 
-         // The coder name:
 
-         //   - address, uint256, tuple, array, etc.
 
-         name;
 
-         // The fully expanded type, including composite types:
 
-         //   - address, uint256, tuple(address,bytes), uint256[3][4][],  etc.
 
-         type;
 
-         // The localName bound in the signature, in this example it is "baz":
 
-         //   - tuple(address foo, uint bar) baz
 
-         localName;
 
-         // Whether this type is dynamic:
 
-         //  - Dynamic: bytes, string, address[], tuple(boolean[]), etc.
 
-         //  - Not Dynamic: address, uint256, boolean[3], tuple(address, uint8)
 
-         dynamic;
 
-         constructor(name, type, localName, dynamic) {
 
-             defineProperties(this, { name, type, localName, dynamic }, {
 
-                 name: "string", type: "string", localName: "string", dynamic: "boolean"
 
-             });
 
-         }
 
-         _throwError(message, value) {
 
-             assertArgument(false, message, this.localName, value);
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class Writer {
 
-         // An array of WordSize lengthed objects to concatenation
 
-         #data;
 
-         #dataLength;
 
-         constructor() {
 
-             this.#data = [];
 
-             this.#dataLength = 0;
 
-         }
 
-         get data() {
 
-             return concat(this.#data);
 
-         }
 
-         get length() { return this.#dataLength; }
 
-         #writeData(data) {
 
-             this.#data.push(data);
 
-             this.#dataLength += data.length;
 
-             return data.length;
 
-         }
 
-         appendWriter(writer) {
 
-             return this.#writeData(getBytesCopy(writer.data));
 
-         }
 
-         // Arrayish item; pad on the right to *nearest* WordSize
 
-         writeBytes(value) {
 
-             let bytes = getBytesCopy(value);
 
-             const paddingOffset = bytes.length % WordSize;
 
-             if (paddingOffset) {
 
-                 bytes = getBytesCopy(concat([bytes, Padding.slice(paddingOffset)]));
 
-             }
 
-             return this.#writeData(bytes);
 
-         }
 
-         // Numeric item; pad on the left *to* WordSize
 
-         writeValue(value) {
 
-             return this.#writeData(getValue$1(value));
 
-         }
 
-         // Inserts a numeric place-holder, returning a callback that can
 
-         // be used to asjust the value later
 
-         writeUpdatableValue() {
 
-             const offset = this.#data.length;
 
-             this.#data.push(Padding);
 
-             this.#dataLength += WordSize;
 
-             return (value) => {
 
-                 this.#data[offset] = getValue$1(value);
 
-             };
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class Reader {
 
-         // Allows incomplete unpadded data to be read; otherwise an error
 
-         // is raised if attempting to overrun the buffer. This is required
 
-         // to deal with an old Solidity bug, in which event data for
 
-         // external (not public thoguh) was tightly packed.
 
-         allowLoose;
 
-         #data;
 
-         #offset;
 
-         #bytesRead;
 
-         #parent;
 
-         #maxInflation;
 
-         constructor(data, allowLoose, maxInflation) {
 
-             defineProperties(this, { allowLoose: !!allowLoose });
 
-             this.#data = getBytesCopy(data);
 
-             this.#bytesRead = 0;
 
-             this.#parent = null;
 
-             this.#maxInflation = (maxInflation != null) ? maxInflation : 1024;
 
-             this.#offset = 0;
 
-         }
 
-         get data() { return hexlify(this.#data); }
 
-         get dataLength() { return this.#data.length; }
 
-         get consumed() { return this.#offset; }
 
-         get bytes() { return new Uint8Array(this.#data); }
 
-         #incrementBytesRead(count) {
 
-             if (this.#parent) {
 
-                 return this.#parent.#incrementBytesRead(count);
 
-             }
 
-             this.#bytesRead += count;
 
-             // Check for excessive inflation (see: #4537)
 
-             assert(this.#maxInflation < 1 || this.#bytesRead <= this.#maxInflation * this.dataLength, `compressed ABI data exceeds inflation ratio of ${this.#maxInflation} ( see: https:/\/github.com/ethers-io/ethers.js/issues/4537 )`, "BUFFER_OVERRUN", {
 
-                 buffer: getBytesCopy(this.#data), offset: this.#offset,
 
-                 length: count, info: {
 
-                     bytesRead: this.#bytesRead,
 
-                     dataLength: this.dataLength
 
-                 }
 
-             });
 
-         }
 
-         #peekBytes(offset, length, loose) {
 
-             let alignedLength = Math.ceil(length / WordSize) * WordSize;
 
-             if (this.#offset + alignedLength > this.#data.length) {
 
-                 if (this.allowLoose && loose && this.#offset + length <= this.#data.length) {
 
-                     alignedLength = length;
 
-                 }
 
-                 else {
 
-                     assert(false, "data out-of-bounds", "BUFFER_OVERRUN", {
 
-                         buffer: getBytesCopy(this.#data),
 
-                         length: this.#data.length,
 
-                         offset: this.#offset + alignedLength
 
-                     });
 
-                 }
 
-             }
 
-             return this.#data.slice(this.#offset, this.#offset + alignedLength);
 
-         }
 
-         // Create a sub-reader with the same underlying data, but offset
 
-         subReader(offset) {
 
-             const reader = new Reader(this.#data.slice(this.#offset + offset), this.allowLoose, this.#maxInflation);
 
-             reader.#parent = this;
 
-             return reader;
 
-         }
 
-         // Read bytes
 
-         readBytes(length, loose) {
 
-             let bytes = this.#peekBytes(0, length, !!loose);
 
-             this.#incrementBytesRead(length);
 
-             this.#offset += bytes.length;
 
-             // @TODO: Make sure the length..end bytes are all 0?
 
-             return bytes.slice(0, length);
 
-         }
 
-         // Read a numeric values
 
-         readValue() {
 
-             return toBigInt(this.readBytes(WordSize));
 
-         }
 
-         readIndex() {
 
-             return toNumber(this.readBytes(WordSize));
 
-         }
 
-     }
 
-     function number(n) {
 
-         if (!Number.isSafeInteger(n) || n < 0)
 
-             throw new Error(`Wrong positive integer: ${n}`);
 
-     }
 
-     function bytes(b, ...lengths) {
 
-         if (!(b instanceof Uint8Array))
 
-             throw new Error('Expected Uint8Array');
 
-         if (lengths.length > 0 && !lengths.includes(b.length))
 
-             throw new Error(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
 
-     }
 
-     function hash(hash) {
 
-         if (typeof hash !== 'function' || typeof hash.create !== 'function')
 
-             throw new Error('Hash should be wrapped by utils.wrapConstructor');
 
-         number(hash.outputLen);
 
-         number(hash.blockLen);
 
-     }
 
-     function exists(instance, checkFinished = true) {
 
-         if (instance.destroyed)
 
-             throw new Error('Hash instance has been destroyed');
 
-         if (checkFinished && instance.finished)
 
-             throw new Error('Hash#digest() has already been called');
 
-     }
 
-     function output(out, instance) {
 
-         bytes(out);
 
-         const min = instance.outputLen;
 
-         if (out.length < min) {
 
-             throw new Error(`digestInto() expects output buffer of length at least ${min}`);
 
-         }
 
-     }
 
-     const crypto$1 = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
 
-     /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
 
-     // We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
 
-     // node.js versions earlier than v19 don't declare it in global scope.
 
-     // For node.js, package.json#exports field mapping rewrites import
 
-     // from `crypto` to `cryptoNode`, which imports native module.
 
-     // Makes the utils un-importable in browsers without a bundler.
 
-     // Once node.js 18 is deprecated, we can just drop the import.
 
-     const u8a$1 = (a) => a instanceof Uint8Array;
 
-     const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
 
-     // Cast array to view
 
-     const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
 
-     // The rotate right (circular right shift) operation for uint32
 
-     const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);
 
-     // big-endian hardware is rare. Just in case someone still decides to run hashes:
 
-     // early-throw an error because we don't support BE yet.
 
-     const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
 
-     if (!isLE)
 
-         throw new Error('Non little-endian hardware is not supported');
 
-     // There is no setImmediate in browser and setTimeout is slow.
 
-     // call of async fn will return Promise, which will be fullfiled only on
 
-     // next scheduler queue processing step and this is exactly what we need.
 
-     const nextTick = async () => { };
 
-     // Returns control to thread each 'tick' ms to avoid blocking
 
-     async function asyncLoop(iters, tick, cb) {
 
-         let ts = Date.now();
 
-         for (let i = 0; i < iters; i++) {
 
-             cb(i);
 
-             // Date.now() is not monotonic, so in case if clock goes backwards we return return control too
 
-             const diff = Date.now() - ts;
 
-             if (diff >= 0 && diff < tick)
 
-                 continue;
 
-             await nextTick();
 
-             ts += diff;
 
-         }
 
-     }
 
-     /**
 
-      * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
 
-      */
 
-     function utf8ToBytes$1(str) {
 
-         if (typeof str !== 'string')
 
-             throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
 
-         return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
 
-     }
 
-     /**
 
-      * Normalizes (non-hex) string or Uint8Array to Uint8Array.
 
-      * Warning: when Uint8Array is passed, it would NOT get copied.
 
-      * Keep in mind for future mutable operations.
 
-      */
 
-     function toBytes(data) {
 
-         if (typeof data === 'string')
 
-             data = utf8ToBytes$1(data);
 
-         if (!u8a$1(data))
 
-             throw new Error(`expected Uint8Array, got ${typeof data}`);
 
-         return data;
 
-     }
 
-     /**
 
-      * Copies several Uint8Arrays into one.
 
-      */
 
-     function concatBytes$1(...arrays) {
 
-         const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
 
-         let pad = 0; // walk through each item, ensure they have proper type
 
-         arrays.forEach((a) => {
 
-             if (!u8a$1(a))
 
-                 throw new Error('Uint8Array expected');
 
-             r.set(a, pad);
 
-             pad += a.length;
 
-         });
 
-         return r;
 
-     }
 
-     // For runtime check if class implements interface
 
-     class Hash {
 
-         // Safe version that clones internal state
 
-         clone() {
 
-             return this._cloneInto();
 
-         }
 
-     }
 
-     const toStr = {}.toString;
 
-     function checkOpts(defaults, opts) {
 
-         if (opts !== undefined && toStr.call(opts) !== '[object Object]')
 
-             throw new Error('Options should be object or undefined');
 
-         const merged = Object.assign(defaults, opts);
 
-         return merged;
 
-     }
 
-     function wrapConstructor(hashCons) {
 
-         const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
 
-         const tmp = hashCons();
 
-         hashC.outputLen = tmp.outputLen;
 
-         hashC.blockLen = tmp.blockLen;
 
-         hashC.create = () => hashCons();
 
-         return hashC;
 
-     }
 
-     /**
 
-      * Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS.
 
-      */
 
-     function randomBytes$2(bytesLength = 32) {
 
-         if (crypto$1 && typeof crypto$1.getRandomValues === 'function') {
 
-             return crypto$1.getRandomValues(new Uint8Array(bytesLength));
 
-         }
 
-         throw new Error('crypto.getRandomValues must be defined');
 
-     }
 
-     // HMAC (RFC 2104)
 
-     class HMAC extends Hash {
 
-         constructor(hash$1, _key) {
 
-             super();
 
-             this.finished = false;
 
-             this.destroyed = false;
 
-             hash(hash$1);
 
-             const key = toBytes(_key);
 
-             this.iHash = hash$1.create();
 
-             if (typeof this.iHash.update !== 'function')
 
-                 throw new Error('Expected instance of class which extends utils.Hash');
 
-             this.blockLen = this.iHash.blockLen;
 
-             this.outputLen = this.iHash.outputLen;
 
-             const blockLen = this.blockLen;
 
-             const pad = new Uint8Array(blockLen);
 
-             // blockLen can be bigger than outputLen
 
-             pad.set(key.length > blockLen ? hash$1.create().update(key).digest() : key);
 
-             for (let i = 0; i < pad.length; i++)
 
-                 pad[i] ^= 0x36;
 
-             this.iHash.update(pad);
 
-             // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
 
-             this.oHash = hash$1.create();
 
-             // Undo internal XOR && apply outer XOR
 
-             for (let i = 0; i < pad.length; i++)
 
-                 pad[i] ^= 0x36 ^ 0x5c;
 
-             this.oHash.update(pad);
 
-             pad.fill(0);
 
-         }
 
-         update(buf) {
 
-             exists(this);
 
-             this.iHash.update(buf);
 
-             return this;
 
-         }
 
-         digestInto(out) {
 
-             exists(this);
 
-             bytes(out, this.outputLen);
 
-             this.finished = true;
 
-             this.iHash.digestInto(out);
 
-             this.oHash.update(out);
 
-             this.oHash.digestInto(out);
 
-             this.destroy();
 
-         }
 
-         digest() {
 
-             const out = new Uint8Array(this.oHash.outputLen);
 
-             this.digestInto(out);
 
-             return out;
 
-         }
 
-         _cloneInto(to) {
 
-             // Create new instance without calling constructor since key already in state and we don't know it.
 
-             to || (to = Object.create(Object.getPrototypeOf(this), {}));
 
-             const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
 
-             to = to;
 
-             to.finished = finished;
 
-             to.destroyed = destroyed;
 
-             to.blockLen = blockLen;
 
-             to.outputLen = outputLen;
 
-             to.oHash = oHash._cloneInto(to.oHash);
 
-             to.iHash = iHash._cloneInto(to.iHash);
 
-             return to;
 
-         }
 
-         destroy() {
 
-             this.destroyed = true;
 
-             this.oHash.destroy();
 
-             this.iHash.destroy();
 
-         }
 
-     }
 
-     /**
 
-      * HMAC: RFC2104 message authentication code.
 
-      * @param hash - function that would be used e.g. sha256
 
-      * @param key - message key
 
-      * @param message - message data
 
-      */
 
-     const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
 
-     hmac.create = (hash, key) => new HMAC(hash, key);
 
-     // Common prologue and epilogue for sync/async functions
 
-     function pbkdf2Init(hash$1, _password, _salt, _opts) {
 
-         hash(hash$1);
 
-         const opts = checkOpts({ dkLen: 32, asyncTick: 10 }, _opts);
 
-         const { c, dkLen, asyncTick } = opts;
 
-         number(c);
 
-         number(dkLen);
 
-         number(asyncTick);
 
-         if (c < 1)
 
-             throw new Error('PBKDF2: iterations (c) should be >= 1');
 
-         const password = toBytes(_password);
 
-         const salt = toBytes(_salt);
 
-         // DK = PBKDF2(PRF, Password, Salt, c, dkLen);
 
-         const DK = new Uint8Array(dkLen);
 
-         // U1 = PRF(Password, Salt + INT_32_BE(i))
 
-         const PRF = hmac.create(hash$1, password);
 
-         const PRFSalt = PRF._cloneInto().update(salt);
 
-         return { c, dkLen, asyncTick, DK, PRF, PRFSalt };
 
-     }
 
-     function pbkdf2Output(PRF, PRFSalt, DK, prfW, u) {
 
-         PRF.destroy();
 
-         PRFSalt.destroy();
 
-         if (prfW)
 
-             prfW.destroy();
 
-         u.fill(0);
 
-         return DK;
 
-     }
 
-     /**
 
-      * PBKDF2-HMAC: RFC 2898 key derivation function
 
-      * @param hash - hash function that would be used e.g. sha256
 
-      * @param password - password from which a derived key is generated
 
-      * @param salt - cryptographic salt
 
-      * @param opts - {c, dkLen} where c is work factor and dkLen is output message size
 
-      */
 
-     function pbkdf2$1(hash, password, salt, opts) {
 
-         const { c, dkLen, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);
 
-         let prfW; // Working copy
 
-         const arr = new Uint8Array(4);
 
-         const view = createView(arr);
 
-         const u = new Uint8Array(PRF.outputLen);
 
-         // DK = T1 + T2 + ⋯ + Tdklen/hlen
 
-         for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {
 
-             // Ti = F(Password, Salt, c, i)
 
-             const Ti = DK.subarray(pos, pos + PRF.outputLen);
 
-             view.setInt32(0, ti, false);
 
-             // F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc
 
-             // U1 = PRF(Password, Salt + INT_32_BE(i))
 
-             (prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);
 
-             Ti.set(u.subarray(0, Ti.length));
 
-             for (let ui = 1; ui < c; ui++) {
 
-                 // Uc = PRF(Password, Uc−1)
 
-                 PRF._cloneInto(prfW).update(u).digestInto(u);
 
-                 for (let i = 0; i < Ti.length; i++)
 
-                     Ti[i] ^= u[i];
 
-             }
 
-         }
 
-         return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);
 
-     }
 
-     // Polyfill for Safari 14
 
-     function setBigUint64(view, byteOffset, value, isLE) {
 
-         if (typeof view.setBigUint64 === 'function')
 
-             return view.setBigUint64(byteOffset, value, isLE);
 
-         const _32n = BigInt(32);
 
-         const _u32_max = BigInt(0xffffffff);
 
-         const wh = Number((value >> _32n) & _u32_max);
 
-         const wl = Number(value & _u32_max);
 
-         const h = isLE ? 4 : 0;
 
-         const l = isLE ? 0 : 4;
 
-         view.setUint32(byteOffset + h, wh, isLE);
 
-         view.setUint32(byteOffset + l, wl, isLE);
 
-     }
 
-     // Base SHA2 class (RFC 6234)
 
-     class SHA2 extends Hash {
 
-         constructor(blockLen, outputLen, padOffset, isLE) {
 
-             super();
 
-             this.blockLen = blockLen;
 
-             this.outputLen = outputLen;
 
-             this.padOffset = padOffset;
 
-             this.isLE = isLE;
 
-             this.finished = false;
 
-             this.length = 0;
 
-             this.pos = 0;
 
-             this.destroyed = false;
 
-             this.buffer = new Uint8Array(blockLen);
 
-             this.view = createView(this.buffer);
 
-         }
 
-         update(data) {
 
-             exists(this);
 
-             const { view, buffer, blockLen } = this;
 
-             data = toBytes(data);
 
-             const len = data.length;
 
-             for (let pos = 0; pos < len;) {
 
-                 const take = Math.min(blockLen - this.pos, len - pos);
 
-                 // Fast path: we have at least one block in input, cast it to view and process
 
-                 if (take === blockLen) {
 
-                     const dataView = createView(data);
 
-                     for (; blockLen <= len - pos; pos += blockLen)
 
-                         this.process(dataView, pos);
 
-                     continue;
 
-                 }
 
-                 buffer.set(data.subarray(pos, pos + take), this.pos);
 
-                 this.pos += take;
 
-                 pos += take;
 
-                 if (this.pos === blockLen) {
 
-                     this.process(view, 0);
 
-                     this.pos = 0;
 
-                 }
 
-             }
 
-             this.length += data.length;
 
-             this.roundClean();
 
-             return this;
 
-         }
 
-         digestInto(out) {
 
-             exists(this);
 
-             output(out, this);
 
-             this.finished = true;
 
-             // Padding
 
-             // We can avoid allocation of buffer for padding completely if it
 
-             // was previously not allocated here. But it won't change performance.
 
-             const { buffer, view, blockLen, isLE } = this;
 
-             let { pos } = this;
 
-             // append the bit '1' to the message
 
-             buffer[pos++] = 0b10000000;
 
-             this.buffer.subarray(pos).fill(0);
 
-             // we have less than padOffset left in buffer, so we cannot put length in current block, need process it and pad again
 
-             if (this.padOffset > blockLen - pos) {
 
-                 this.process(view, 0);
 
-                 pos = 0;
 
-             }
 
-             // Pad until full block byte with zeros
 
-             for (let i = pos; i < blockLen; i++)
 
-                 buffer[i] = 0;
 
-             // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
 
-             // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
 
-             // So we just write lowest 64 bits of that value.
 
-             setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
 
-             this.process(view, 0);
 
-             const oview = createView(out);
 
-             const len = this.outputLen;
 
-             // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
 
-             if (len % 4)
 
-                 throw new Error('_sha2: outputLen should be aligned to 32bit');
 
-             const outLen = len / 4;
 
-             const state = this.get();
 
-             if (outLen > state.length)
 
-                 throw new Error('_sha2: outputLen bigger than state');
 
-             for (let i = 0; i < outLen; i++)
 
-                 oview.setUint32(4 * i, state[i], isLE);
 
-         }
 
-         digest() {
 
-             const { buffer, outputLen } = this;
 
-             this.digestInto(buffer);
 
-             const res = buffer.slice(0, outputLen);
 
-             this.destroy();
 
-             return res;
 
-         }
 
-         _cloneInto(to) {
 
-             to || (to = new this.constructor());
 
-             to.set(...this.get());
 
-             const { blockLen, buffer, length, finished, destroyed, pos } = this;
 
-             to.length = length;
 
-             to.pos = pos;
 
-             to.finished = finished;
 
-             to.destroyed = destroyed;
 
-             if (length % blockLen)
 
-                 to.buffer.set(buffer);
 
-             return to;
 
-         }
 
-     }
 
-     // SHA2-256 need to try 2^128 hashes to execute birthday attack.
 
-     // BTC network is doing 2^67 hashes/sec as per early 2023.
 
-     // Choice: a ? b : c
 
-     const Chi = (a, b, c) => (a & b) ^ (~a & c);
 
-     // Majority function, true if any two inpust is true
 
-     const Maj = (a, b, c) => (a & b) ^ (a & c) ^ (b & c);
 
-     // Round constants:
 
-     // first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
 
-     // prettier-ignore
 
-     const SHA256_K = /* @__PURE__ */ new Uint32Array([
 
-         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
 
-         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
 
-         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
 
-         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
 
-         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
 
-         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
 
-         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
 
-         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
 
-     ]);
 
-     // Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
 
-     // prettier-ignore
 
-     const IV = /* @__PURE__ */ new Uint32Array([
 
-         0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
 
-     ]);
 
-     // Temporary buffer, not used to store anything between runs
 
-     // Named this way because it matches specification.
 
-     const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
 
-     class SHA256 extends SHA2 {
 
-         constructor() {
 
-             super(64, 32, 8, false);
 
-             // We cannot use array here since array allows indexing by variable
 
-             // which means optimizer/compiler cannot use registers.
 
-             this.A = IV[0] | 0;
 
-             this.B = IV[1] | 0;
 
-             this.C = IV[2] | 0;
 
-             this.D = IV[3] | 0;
 
-             this.E = IV[4] | 0;
 
-             this.F = IV[5] | 0;
 
-             this.G = IV[6] | 0;
 
-             this.H = IV[7] | 0;
 
-         }
 
-         get() {
 
-             const { A, B, C, D, E, F, G, H } = this;
 
-             return [A, B, C, D, E, F, G, H];
 
-         }
 
-         // prettier-ignore
 
-         set(A, B, C, D, E, F, G, H) {
 
-             this.A = A | 0;
 
-             this.B = B | 0;
 
-             this.C = C | 0;
 
-             this.D = D | 0;
 
-             this.E = E | 0;
 
-             this.F = F | 0;
 
-             this.G = G | 0;
 
-             this.H = H | 0;
 
-         }
 
-         process(view, offset) {
 
-             // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array
 
-             for (let i = 0; i < 16; i++, offset += 4)
 
-                 SHA256_W[i] = view.getUint32(offset, false);
 
-             for (let i = 16; i < 64; i++) {
 
-                 const W15 = SHA256_W[i - 15];
 
-                 const W2 = SHA256_W[i - 2];
 
-                 const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);
 
-                 const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);
 
-                 SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;
 
-             }
 
-             // Compression function main loop, 64 rounds
 
-             let { A, B, C, D, E, F, G, H } = this;
 
-             for (let i = 0; i < 64; i++) {
 
-                 const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
 
-                 const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
 
-                 const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
 
-                 const T2 = (sigma0 + Maj(A, B, C)) | 0;
 
-                 H = G;
 
-                 G = F;
 
-                 F = E;
 
-                 E = (D + T1) | 0;
 
-                 D = C;
 
-                 C = B;
 
-                 B = A;
 
-                 A = (T1 + T2) | 0;
 
-             }
 
-             // Add the compressed chunk to the current hash value
 
-             A = (A + this.A) | 0;
 
-             B = (B + this.B) | 0;
 
-             C = (C + this.C) | 0;
 
-             D = (D + this.D) | 0;
 
-             E = (E + this.E) | 0;
 
-             F = (F + this.F) | 0;
 
-             G = (G + this.G) | 0;
 
-             H = (H + this.H) | 0;
 
-             this.set(A, B, C, D, E, F, G, H);
 
-         }
 
-         roundClean() {
 
-             SHA256_W.fill(0);
 
-         }
 
-         destroy() {
 
-             this.set(0, 0, 0, 0, 0, 0, 0, 0);
 
-             this.buffer.fill(0);
 
-         }
 
-     }
 
-     /**
 
-      * SHA2-256 hash function
 
-      * @param message - data that would be hashed
 
-      */
 
-     const sha256$1 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
 
-     const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
 
-     const _32n = /* @__PURE__ */ BigInt(32);
 
-     // We are not using BigUint64Array, because they are extremely slow as per 2022
 
-     function fromBig(n, le = false) {
 
-         if (le)
 
-             return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
 
-         return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
 
-     }
 
-     function split$1(lst, le = false) {
 
-         let Ah = new Uint32Array(lst.length);
 
-         let Al = new Uint32Array(lst.length);
 
-         for (let i = 0; i < lst.length; i++) {
 
-             const { h, l } = fromBig(lst[i], le);
 
-             [Ah[i], Al[i]] = [h, l];
 
-         }
 
-         return [Ah, Al];
 
-     }
 
-     const toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);
 
-     // for Shift in [0, 32)
 
-     const shrSH = (h, _l, s) => h >>> s;
 
-     const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
 
-     // Right rotate for Shift in [1, 32)
 
-     const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));
 
-     const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
 
-     // Right rotate for Shift in (32, 64), NOTE: 32 is special case.
 
-     const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));
 
-     const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));
 
-     // Right rotate for shift===32 (just swaps l&h)
 
-     const rotr32H = (_h, l) => l;
 
-     const rotr32L = (h, _l) => h;
 
-     // Left rotate for Shift in [1, 32)
 
-     const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));
 
-     const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));
 
-     // Left rotate for Shift in (32, 64), NOTE: 32 is special case.
 
-     const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));
 
-     const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));
 
-     // JS uses 32-bit signed integers for bitwise operations which means we cannot
 
-     // simple take carry out of low bit sum by shift, we need to use division.
 
-     function add(Ah, Al, Bh, Bl) {
 
-         const l = (Al >>> 0) + (Bl >>> 0);
 
-         return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };
 
-     }
 
-     // Addition with more than 2 elements
 
-     const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
 
-     const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;
 
-     const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
 
-     const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;
 
-     const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
 
-     const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;
 
-     // prettier-ignore
 
-     const u64 = {
 
-         fromBig, split: split$1, toBig,
 
-         shrSH, shrSL,
 
-         rotrSH, rotrSL, rotrBH, rotrBL,
 
-         rotr32H, rotr32L,
 
-         rotlSH, rotlSL, rotlBH, rotlBL,
 
-         add, add3L, add3H, add4L, add4H, add5H, add5L,
 
-     };
 
-     // Round contants (first 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409):
 
-     // prettier-ignore
 
-     const [SHA512_Kh, SHA512_Kl] = /* @__PURE__ */ (() => u64.split([
 
-         '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',
 
-         '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',
 
-         '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',
 
-         '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',
 
-         '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',
 
-         '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',
 
-         '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',
 
-         '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',
 
-         '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',
 
-         '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',
 
-         '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',
 
-         '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',
 
-         '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',
 
-         '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',
 
-         '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',
 
-         '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',
 
-         '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',
 
-         '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',
 
-         '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',
 
-         '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'
 
-     ].map(n => BigInt(n))))();
 
-     // Temporary buffer, not used to store anything between runs
 
-     const SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);
 
-     const SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);
 
-     class SHA512 extends SHA2 {
 
-         constructor() {
 
-             super(128, 64, 16, false);
 
-             // We cannot use array here since array allows indexing by variable which means optimizer/compiler cannot use registers.
 
-             // Also looks cleaner and easier to verify with spec.
 
-             // Initial state (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
 
-             // h -- high 32 bits, l -- low 32 bits
 
-             this.Ah = 0x6a09e667 | 0;
 
-             this.Al = 0xf3bcc908 | 0;
 
-             this.Bh = 0xbb67ae85 | 0;
 
-             this.Bl = 0x84caa73b | 0;
 
-             this.Ch = 0x3c6ef372 | 0;
 
-             this.Cl = 0xfe94f82b | 0;
 
-             this.Dh = 0xa54ff53a | 0;
 
-             this.Dl = 0x5f1d36f1 | 0;
 
-             this.Eh = 0x510e527f | 0;
 
-             this.El = 0xade682d1 | 0;
 
-             this.Fh = 0x9b05688c | 0;
 
-             this.Fl = 0x2b3e6c1f | 0;
 
-             this.Gh = 0x1f83d9ab | 0;
 
-             this.Gl = 0xfb41bd6b | 0;
 
-             this.Hh = 0x5be0cd19 | 0;
 
-             this.Hl = 0x137e2179 | 0;
 
-         }
 
-         // prettier-ignore
 
-         get() {
 
-             const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
 
-             return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];
 
-         }
 
-         // prettier-ignore
 
-         set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {
 
-             this.Ah = Ah | 0;
 
-             this.Al = Al | 0;
 
-             this.Bh = Bh | 0;
 
-             this.Bl = Bl | 0;
 
-             this.Ch = Ch | 0;
 
-             this.Cl = Cl | 0;
 
-             this.Dh = Dh | 0;
 
-             this.Dl = Dl | 0;
 
-             this.Eh = Eh | 0;
 
-             this.El = El | 0;
 
-             this.Fh = Fh | 0;
 
-             this.Fl = Fl | 0;
 
-             this.Gh = Gh | 0;
 
-             this.Gl = Gl | 0;
 
-             this.Hh = Hh | 0;
 
-             this.Hl = Hl | 0;
 
-         }
 
-         process(view, offset) {
 
-             // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array
 
-             for (let i = 0; i < 16; i++, offset += 4) {
 
-                 SHA512_W_H[i] = view.getUint32(offset);
 
-                 SHA512_W_L[i] = view.getUint32((offset += 4));
 
-             }
 
-             for (let i = 16; i < 80; i++) {
 
-                 // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)
 
-                 const W15h = SHA512_W_H[i - 15] | 0;
 
-                 const W15l = SHA512_W_L[i - 15] | 0;
 
-                 const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7);
 
-                 const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7);
 
-                 // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)
 
-                 const W2h = SHA512_W_H[i - 2] | 0;
 
-                 const W2l = SHA512_W_L[i - 2] | 0;
 
-                 const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6);
 
-                 const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6);
 
-                 // SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16];
 
-                 const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);
 
-                 const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);
 
-                 SHA512_W_H[i] = SUMh | 0;
 
-                 SHA512_W_L[i] = SUMl | 0;
 
-             }
 
-             let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
 
-             // Compression function main loop, 80 rounds
 
-             for (let i = 0; i < 80; i++) {
 
-                 // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)
 
-                 const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41);
 
-                 const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41);
 
-                 //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
 
-                 const CHIh = (Eh & Fh) ^ (~Eh & Gh);
 
-                 const CHIl = (El & Fl) ^ (~El & Gl);
 
-                 // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]
 
-                 // prettier-ignore
 
-                 const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);
 
-                 const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);
 
-                 const T1l = T1ll | 0;
 
-                 // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)
 
-                 const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39);
 
-                 const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39);
 
-                 const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);
 
-                 const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);
 
-                 Hh = Gh | 0;
 
-                 Hl = Gl | 0;
 
-                 Gh = Fh | 0;
 
-                 Gl = Fl | 0;
 
-                 Fh = Eh | 0;
 
-                 Fl = El | 0;
 
-                 ({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));
 
-                 Dh = Ch | 0;
 
-                 Dl = Cl | 0;
 
-                 Ch = Bh | 0;
 
-                 Cl = Bl | 0;
 
-                 Bh = Ah | 0;
 
-                 Bl = Al | 0;
 
-                 const All = u64.add3L(T1l, sigma0l, MAJl);
 
-                 Ah = u64.add3H(All, T1h, sigma0h, MAJh);
 
-                 Al = All | 0;
 
-             }
 
-             // Add the compressed chunk to the current hash value
 
-             ({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));
 
-             ({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));
 
-             ({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));
 
-             ({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));
 
-             ({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));
 
-             ({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));
 
-             ({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));
 
-             ({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));
 
-             this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);
 
-         }
 
-         roundClean() {
 
-             SHA512_W_H.fill(0);
 
-             SHA512_W_L.fill(0);
 
-         }
 
-         destroy() {
 
-             this.buffer.fill(0);
 
-             this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
-         }
 
-     }
 
-     const sha512$1 = /* @__PURE__ */ wrapConstructor(() => new SHA512());
 
-     /* Browser Crypto Shims */
 
-     function getGlobal$1() {
 
-         if (typeof self !== 'undefined') {
 
-             return self;
 
-         }
 
-         if (typeof window !== 'undefined') {
 
-             return window;
 
-         }
 
-         if (typeof global !== 'undefined') {
 
-             return global;
 
-         }
 
-         throw new Error('unable to locate global object');
 
-     }
 
-     const anyGlobal = getGlobal$1();
 
-     const crypto = anyGlobal.crypto || anyGlobal.msCrypto;
 
-     function createHash(algo) {
 
-         switch (algo) {
 
-             case "sha256": return sha256$1.create();
 
-             case "sha512": return sha512$1.create();
 
-         }
 
-         assertArgument(false, "invalid hashing algorithm name", "algorithm", algo);
 
-     }
 
-     function createHmac(_algo, key) {
 
-         const algo = ({ sha256: sha256$1, sha512: sha512$1 }[_algo]);
 
-         assertArgument(algo != null, "invalid hmac algorithm", "algorithm", _algo);
 
-         return hmac.create(algo, key);
 
-     }
 
-     function pbkdf2Sync(password, salt, iterations, keylen, _algo) {
 
-         const algo = ({ sha256: sha256$1, sha512: sha512$1 }[_algo]);
 
-         assertArgument(algo != null, "invalid pbkdf2 algorithm", "algorithm", _algo);
 
-         return pbkdf2$1(algo, password, salt, { c: iterations, dkLen: keylen });
 
-     }
 
-     function randomBytes$1(length) {
 
-         assert(crypto != null, "platform does not support secure random numbers", "UNSUPPORTED_OPERATION", {
 
-             operation: "randomBytes"
 
-         });
 
-         assertArgument(Number.isInteger(length) && length > 0 && length <= 1024, "invalid length", "length", length);
 
-         const result = new Uint8Array(length);
 
-         crypto.getRandomValues(result);
 
-         return result;
 
-     }
 
-     /**
 
-      *  An **HMAC** enables verification that a given key was used
 
-      *  to authenticate a payload.
 
-      *
 
-      *  See: [[link-wiki-hmac]]
 
-      *
 
-      *  @_subsection: api/crypto:HMAC  [about-hmac]
 
-      */
 
-     let locked$4 = false;
 
-     const _computeHmac = function (algorithm, key, data) {
 
-         return createHmac(algorithm, key).update(data).digest();
 
-     };
 
-     let __computeHmac = _computeHmac;
 
-     /**
 
-      *  Return the HMAC for %%data%% using the %%key%% key with the underlying
 
-      *  %%algo%% used for compression.
 
-      *
 
-      *  @example:
 
-      *    key = id("some-secret")
 
-      *
 
-      *    // Compute the HMAC
 
-      *    computeHmac("sha256", key, "0x1337")
 
-      *    //_result:
 
-      *
 
-      *    // To compute the HMAC of UTF-8 data, the data must be
 
-      *    // converted to UTF-8 bytes
 
-      *    computeHmac("sha256", key, toUtf8Bytes("Hello World"))
 
-      *    //_result:
 
-      *
 
-      */
 
-     function computeHmac(algorithm, _key, _data) {
 
-         const key = getBytes(_key, "key");
 
-         const data = getBytes(_data, "data");
 
-         return hexlify(__computeHmac(algorithm, key, data));
 
-     }
 
-     computeHmac._ = _computeHmac;
 
-     computeHmac.lock = function () { locked$4 = true; };
 
-     computeHmac.register = function (func) {
 
-         if (locked$4) {
 
-             throw new Error("computeHmac is locked");
 
-         }
 
-         __computeHmac = func;
 
-     };
 
-     Object.freeze(computeHmac);
 
-     // SHA3 (keccak) is based on a new design: basically, the internal state is bigger than output size.
 
-     // It's called a sponge function.
 
-     // Various per round constants calculations
 
-     const [SHA3_PI, SHA3_ROTL, _SHA3_IOTA] = [[], [], []];
 
-     const _0n$4 = /* @__PURE__ */ BigInt(0);
 
-     const _1n$5 = /* @__PURE__ */ BigInt(1);
 
-     const _2n$3 = /* @__PURE__ */ BigInt(2);
 
-     const _7n = /* @__PURE__ */ BigInt(7);
 
-     const _256n = /* @__PURE__ */ BigInt(256);
 
-     const _0x71n = /* @__PURE__ */ BigInt(0x71);
 
-     for (let round = 0, R = _1n$5, x = 1, y = 0; round < 24; round++) {
 
-         // Pi
 
-         [x, y] = [y, (2 * x + 3 * y) % 5];
 
-         SHA3_PI.push(2 * (5 * y + x));
 
-         // Rotational
 
-         SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);
 
-         // Iota
 
-         let t = _0n$4;
 
-         for (let j = 0; j < 7; j++) {
 
-             R = ((R << _1n$5) ^ ((R >> _7n) * _0x71n)) % _256n;
 
-             if (R & _2n$3)
 
-                 t ^= _1n$5 << ((_1n$5 << /* @__PURE__ */ BigInt(j)) - _1n$5);
 
-         }
 
-         _SHA3_IOTA.push(t);
 
-     }
 
-     const [SHA3_IOTA_H, SHA3_IOTA_L] = /* @__PURE__ */ split$1(_SHA3_IOTA, true);
 
-     // Left rotation (without 0, 32, 64)
 
-     const rotlH = (h, l, s) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s));
 
-     const rotlL = (h, l, s) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s));
 
-     // Same as keccakf1600, but allows to skip some rounds
 
-     function keccakP(s, rounds = 24) {
 
-         const B = new Uint32Array(5 * 2);
 
-         // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)
 
-         for (let round = 24 - rounds; round < 24; round++) {
 
-             // Theta θ
 
-             for (let x = 0; x < 10; x++)
 
-                 B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
 
-             for (let x = 0; x < 10; x += 2) {
 
-                 const idx1 = (x + 8) % 10;
 
-                 const idx0 = (x + 2) % 10;
 
-                 const B0 = B[idx0];
 
-                 const B1 = B[idx0 + 1];
 
-                 const Th = rotlH(B0, B1, 1) ^ B[idx1];
 
-                 const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
 
-                 for (let y = 0; y < 50; y += 10) {
 
-                     s[x + y] ^= Th;
 
-                     s[x + y + 1] ^= Tl;
 
-                 }
 
-             }
 
-             // Rho (ρ) and Pi (π)
 
-             let curH = s[2];
 
-             let curL = s[3];
 
-             for (let t = 0; t < 24; t++) {
 
-                 const shift = SHA3_ROTL[t];
 
-                 const Th = rotlH(curH, curL, shift);
 
-                 const Tl = rotlL(curH, curL, shift);
 
-                 const PI = SHA3_PI[t];
 
-                 curH = s[PI];
 
-                 curL = s[PI + 1];
 
-                 s[PI] = Th;
 
-                 s[PI + 1] = Tl;
 
-             }
 
-             // Chi (χ)
 
-             for (let y = 0; y < 50; y += 10) {
 
-                 for (let x = 0; x < 10; x++)
 
-                     B[x] = s[y + x];
 
-                 for (let x = 0; x < 10; x++)
 
-                     s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
 
-             }
 
-             // Iota (ι)
 
-             s[0] ^= SHA3_IOTA_H[round];
 
-             s[1] ^= SHA3_IOTA_L[round];
 
-         }
 
-         B.fill(0);
 
-     }
 
-     class Keccak extends Hash {
 
-         // NOTE: we accept arguments in bytes instead of bits here.
 
-         constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
 
-             super();
 
-             this.blockLen = blockLen;
 
-             this.suffix = suffix;
 
-             this.outputLen = outputLen;
 
-             this.enableXOF = enableXOF;
 
-             this.rounds = rounds;
 
-             this.pos = 0;
 
-             this.posOut = 0;
 
-             this.finished = false;
 
-             this.destroyed = false;
 
-             // Can be passed from user as dkLen
 
-             number(outputLen);
 
-             // 1600 = 5x5 matrix of 64bit.  1600 bits === 200 bytes
 
-             if (0 >= this.blockLen || this.blockLen >= 200)
 
-                 throw new Error('Sha3 supports only keccak-f1600 function');
 
-             this.state = new Uint8Array(200);
 
-             this.state32 = u32(this.state);
 
-         }
 
-         keccak() {
 
-             keccakP(this.state32, this.rounds);
 
-             this.posOut = 0;
 
-             this.pos = 0;
 
-         }
 
-         update(data) {
 
-             exists(this);
 
-             const { blockLen, state } = this;
 
-             data = toBytes(data);
 
-             const len = data.length;
 
-             for (let pos = 0; pos < len;) {
 
-                 const take = Math.min(blockLen - this.pos, len - pos);
 
-                 for (let i = 0; i < take; i++)
 
-                     state[this.pos++] ^= data[pos++];
 
-                 if (this.pos === blockLen)
 
-                     this.keccak();
 
-             }
 
-             return this;
 
-         }
 
-         finish() {
 
-             if (this.finished)
 
-                 return;
 
-             this.finished = true;
 
-             const { state, suffix, pos, blockLen } = this;
 
-             // Do the padding
 
-             state[pos] ^= suffix;
 
-             if ((suffix & 0x80) !== 0 && pos === blockLen - 1)
 
-                 this.keccak();
 
-             state[blockLen - 1] ^= 0x80;
 
-             this.keccak();
 
-         }
 
-         writeInto(out) {
 
-             exists(this, false);
 
-             bytes(out);
 
-             this.finish();
 
-             const bufferOut = this.state;
 
-             const { blockLen } = this;
 
-             for (let pos = 0, len = out.length; pos < len;) {
 
-                 if (this.posOut >= blockLen)
 
-                     this.keccak();
 
-                 const take = Math.min(blockLen - this.posOut, len - pos);
 
-                 out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
 
-                 this.posOut += take;
 
-                 pos += take;
 
-             }
 
-             return out;
 
-         }
 
-         xofInto(out) {
 
-             // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF
 
-             if (!this.enableXOF)
 
-                 throw new Error('XOF is not possible for this instance');
 
-             return this.writeInto(out);
 
-         }
 
-         xof(bytes) {
 
-             number(bytes);
 
-             return this.xofInto(new Uint8Array(bytes));
 
-         }
 
-         digestInto(out) {
 
-             output(out, this);
 
-             if (this.finished)
 
-                 throw new Error('digest() was already called');
 
-             this.writeInto(out);
 
-             this.destroy();
 
-             return out;
 
-         }
 
-         digest() {
 
-             return this.digestInto(new Uint8Array(this.outputLen));
 
-         }
 
-         destroy() {
 
-             this.destroyed = true;
 
-             this.state.fill(0);
 
-         }
 
-         _cloneInto(to) {
 
-             const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
 
-             to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
 
-             to.state32.set(this.state32);
 
-             to.pos = this.pos;
 
-             to.posOut = this.posOut;
 
-             to.finished = this.finished;
 
-             to.rounds = rounds;
 
-             // Suffix can change in cSHAKE
 
-             to.suffix = suffix;
 
-             to.outputLen = outputLen;
 
-             to.enableXOF = enableXOF;
 
-             to.destroyed = this.destroyed;
 
-             return to;
 
-         }
 
-     }
 
-     const gen = (suffix, blockLen, outputLen) => wrapConstructor(() => new Keccak(blockLen, suffix, outputLen));
 
-     /**
 
-      * keccak-256 hash function. Different from SHA3-256.
 
-      * @param message - that would be hashed
 
-      */
 
-     const keccak_256 = /* @__PURE__ */ gen(0x01, 136, 256 / 8);
 
-     /**
 
-      *  Cryptographic hashing functions
 
-      *
 
-      *  @_subsection: api/crypto:Hash Functions [about-crypto-hashing]
 
-      */
 
-     let locked$3 = false;
 
-     const _keccak256 = function (data) {
 
-         return keccak_256(data);
 
-     };
 
-     let __keccak256 = _keccak256;
 
-     /**
 
-      *  Compute the cryptographic KECCAK256 hash of %%data%%.
 
-      *
 
-      *  The %%data%% **must** be a data representation, to compute the
 
-      *  hash of UTF-8 data use the [[id]] function.
 
-      *
 
-      *  @returns DataHexstring
 
-      *  @example:
 
-      *    keccak256("0x")
 
-      *    //_result:
 
-      *
 
-      *    keccak256("0x1337")
 
-      *    //_result:
 
-      *
 
-      *    keccak256(new Uint8Array([ 0x13, 0x37 ]))
 
-      *    //_result:
 
-      *
 
-      *    // Strings are assumed to be DataHexString, otherwise it will
 
-      *    // throw. To hash UTF-8 data, see the note above.
 
-      *    keccak256("Hello World")
 
-      *    //_error:
 
-      */
 
-     function keccak256(_data) {
 
-         const data = getBytes(_data, "data");
 
-         return hexlify(__keccak256(data));
 
-     }
 
-     keccak256._ = _keccak256;
 
-     keccak256.lock = function () { locked$3 = true; };
 
-     keccak256.register = function (func) {
 
-         if (locked$3) {
 
-             throw new TypeError("keccak256 is locked");
 
-         }
 
-         __keccak256 = func;
 
-     };
 
-     Object.freeze(keccak256);
 
-     // https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
 
-     // https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
 
-     const Rho = /* @__PURE__ */ new Uint8Array([7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8]);
 
-     const Id = /* @__PURE__ */ Uint8Array.from({ length: 16 }, (_, i) => i);
 
-     const Pi = /* @__PURE__ */ Id.map((i) => (9 * i + 5) % 16);
 
-     let idxL = [Id];
 
-     let idxR = [Pi];
 
-     for (let i = 0; i < 4; i++)
 
-         for (let j of [idxL, idxR])
 
-             j.push(j[i].map((k) => Rho[k]));
 
-     const shifts = /* @__PURE__ */ [
 
-         [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
 
-         [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
 
-         [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
 
-         [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
 
-         [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5],
 
-     ].map((i) => new Uint8Array(i));
 
-     const shiftsL = /* @__PURE__ */ idxL.map((idx, i) => idx.map((j) => shifts[i][j]));
 
-     const shiftsR = /* @__PURE__ */ idxR.map((idx, i) => idx.map((j) => shifts[i][j]));
 
-     const Kl = /* @__PURE__ */ new Uint32Array([
 
-         0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e,
 
-     ]);
 
-     const Kr = /* @__PURE__ */ new Uint32Array([
 
-         0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000,
 
-     ]);
 
-     // The rotate left (circular left shift) operation for uint32
 
-     const rotl$1 = (word, shift) => (word << shift) | (word >>> (32 - shift));
 
-     // It's called f() in spec.
 
-     function f(group, x, y, z) {
 
-         if (group === 0)
 
-             return x ^ y ^ z;
 
-         else if (group === 1)
 
-             return (x & y) | (~x & z);
 
-         else if (group === 2)
 
-             return (x | ~y) ^ z;
 
-         else if (group === 3)
 
-             return (x & z) | (y & ~z);
 
-         else
 
-             return x ^ (y | ~z);
 
-     }
 
-     // Temporary buffer, not used to store anything between runs
 
-     const BUF = /* @__PURE__ */ new Uint32Array(16);
 
-     class RIPEMD160 extends SHA2 {
 
-         constructor() {
 
-             super(64, 20, 8, true);
 
-             this.h0 = 0x67452301 | 0;
 
-             this.h1 = 0xefcdab89 | 0;
 
-             this.h2 = 0x98badcfe | 0;
 
-             this.h3 = 0x10325476 | 0;
 
-             this.h4 = 0xc3d2e1f0 | 0;
 
-         }
 
-         get() {
 
-             const { h0, h1, h2, h3, h4 } = this;
 
-             return [h0, h1, h2, h3, h4];
 
-         }
 
-         set(h0, h1, h2, h3, h4) {
 
-             this.h0 = h0 | 0;
 
-             this.h1 = h1 | 0;
 
-             this.h2 = h2 | 0;
 
-             this.h3 = h3 | 0;
 
-             this.h4 = h4 | 0;
 
-         }
 
-         process(view, offset) {
 
-             for (let i = 0; i < 16; i++, offset += 4)
 
-                 BUF[i] = view.getUint32(offset, true);
 
-             // prettier-ignore
 
-             let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;
 
-             // Instead of iterating 0 to 80, we split it into 5 groups
 
-             // And use the groups in constants, functions, etc. Much simpler
 
-             for (let group = 0; group < 5; group++) {
 
-                 const rGroup = 4 - group;
 
-                 const hbl = Kl[group], hbr = Kr[group]; // prettier-ignore
 
-                 const rl = idxL[group], rr = idxR[group]; // prettier-ignore
 
-                 const sl = shiftsL[group], sr = shiftsR[group]; // prettier-ignore
 
-                 for (let i = 0; i < 16; i++) {
 
-                     const tl = (rotl$1(al + f(group, bl, cl, dl) + BUF[rl[i]] + hbl, sl[i]) + el) | 0;
 
-                     al = el, el = dl, dl = rotl$1(cl, 10) | 0, cl = bl, bl = tl; // prettier-ignore
 
-                 }
 
-                 // 2 loops are 10% faster
 
-                 for (let i = 0; i < 16; i++) {
 
-                     const tr = (rotl$1(ar + f(rGroup, br, cr, dr) + BUF[rr[i]] + hbr, sr[i]) + er) | 0;
 
-                     ar = er, er = dr, dr = rotl$1(cr, 10) | 0, cr = br, br = tr; // prettier-ignore
 
-                 }
 
-             }
 
-             // Add the compressed chunk to the current hash value
 
-             this.set((this.h1 + cl + dr) | 0, (this.h2 + dl + er) | 0, (this.h3 + el + ar) | 0, (this.h4 + al + br) | 0, (this.h0 + bl + cr) | 0);
 
-         }
 
-         roundClean() {
 
-             BUF.fill(0);
 
-         }
 
-         destroy() {
 
-             this.destroyed = true;
 
-             this.buffer.fill(0);
 
-             this.set(0, 0, 0, 0, 0);
 
-         }
 
-     }
 
-     /**
 
-      * RIPEMD-160 - a hash function from 1990s.
 
-      * @param message - msg that would be hashed
 
-      */
 
-     const ripemd160$1 = /* @__PURE__ */ wrapConstructor(() => new RIPEMD160());
 
-     let locked$2 = false;
 
-     const _ripemd160 = function (data) {
 
-         return ripemd160$1(data);
 
-     };
 
-     let __ripemd160 = _ripemd160;
 
-     /**
 
-      *  Compute the cryptographic RIPEMD-160 hash of %%data%%.
 
-      *
 
-      *  @_docloc: api/crypto:Hash Functions
 
-      *  @returns DataHexstring
 
-      *
 
-      *  @example:
 
-      *    ripemd160("0x")
 
-      *    //_result:
 
-      *
 
-      *    ripemd160("0x1337")
 
-      *    //_result:
 
-      *
 
-      *    ripemd160(new Uint8Array([ 0x13, 0x37 ]))
 
-      *    //_result:
 
-      *
 
-      */
 
-     function ripemd160(_data) {
 
-         const data = getBytes(_data, "data");
 
-         return hexlify(__ripemd160(data));
 
-     }
 
-     ripemd160._ = _ripemd160;
 
-     ripemd160.lock = function () { locked$2 = true; };
 
-     ripemd160.register = function (func) {
 
-         if (locked$2) {
 
-             throw new TypeError("ripemd160 is locked");
 
-         }
 
-         __ripemd160 = func;
 
-     };
 
-     Object.freeze(ripemd160);
 
-     /**
 
-      *  A **Password-Based Key-Derivation Function** is designed to create
 
-      *  a sequence of bytes suitible as a **key** from a human-rememberable
 
-      *  password.
 
-      *
 
-      *  @_subsection: api/crypto:Passwords  [about-pbkdf]
 
-      */
 
-     let locked$1 = false;
 
-     const _pbkdf2 = function (password, salt, iterations, keylen, algo) {
 
-         return pbkdf2Sync(password, salt, iterations, keylen, algo);
 
-     };
 
-     let __pbkdf2 = _pbkdf2;
 
-     /**
 
-      *  Return the [[link-pbkdf2]] for %%keylen%% bytes for %%password%% using
 
-      *  the %%salt%% and using %%iterations%% of %%algo%%.
 
-      *
 
-      *  This PBKDF is outdated and should not be used in new projects, but is
 
-      *  required to decrypt older files.
 
-      *
 
-      *  @example:
 
-      *    // The password must be converted to bytes, and it is generally
 
-      *    // best practices to ensure the string has been normalized. Many
 
-      *    // formats explicitly indicate the normalization form to use.
 
-      *    password = "hello"
 
-      *    passwordBytes = toUtf8Bytes(password, "NFKC")
 
-      *
 
-      *    salt = id("some-salt")
 
-      *
 
-      *    // Compute the PBKDF2
 
-      *    pbkdf2(passwordBytes, salt, 1024, 16, "sha256")
 
-      *    //_result:
 
-      */
 
-     function pbkdf2(_password, _salt, iterations, keylen, algo) {
 
-         const password = getBytes(_password, "password");
 
-         const salt = getBytes(_salt, "salt");
 
-         return hexlify(__pbkdf2(password, salt, iterations, keylen, algo));
 
-     }
 
-     pbkdf2._ = _pbkdf2;
 
-     pbkdf2.lock = function () { locked$1 = true; };
 
-     pbkdf2.register = function (func) {
 
-         if (locked$1) {
 
-             throw new Error("pbkdf2 is locked");
 
-         }
 
-         __pbkdf2 = func;
 
-     };
 
-     Object.freeze(pbkdf2);
 
-     /**
 
-      *  A **Cryptographically Secure Random Value** is one that has been
 
-      *  generated with additional care take to prevent side-channels
 
-      *  from allowing others to detect it and prevent others from through
 
-      *  coincidence generate the same values.
 
-      *
 
-      *  @_subsection: api/crypto:Random Values  [about-crypto-random]
 
-      */
 
-     let locked = false;
 
-     const _randomBytes = function (length) {
 
-         return new Uint8Array(randomBytes$1(length));
 
-     };
 
-     let __randomBytes = _randomBytes;
 
-     /**
 
-      *  Return %%length%% bytes of cryptographically secure random data.
 
-      *
 
-      *  @example:
 
-      *    randomBytes(8)
 
-      *    //_result:
 
-      */
 
-     function randomBytes(length) {
 
-         return __randomBytes(length);
 
-     }
 
-     randomBytes._ = _randomBytes;
 
-     randomBytes.lock = function () { locked = true; };
 
-     randomBytes.register = function (func) {
 
-         if (locked) {
 
-             throw new Error("randomBytes is locked");
 
-         }
 
-         __randomBytes = func;
 
-     };
 
-     Object.freeze(randomBytes);
 
-     // RFC 7914 Scrypt KDF
 
-     // Left rotate for uint32
 
-     const rotl = (a, b) => (a << b) | (a >>> (32 - b));
 
-     // The main Scrypt loop: uses Salsa extensively.
 
-     // Six versions of the function were tried, this is the fastest one.
 
-     // prettier-ignore
 
-     function XorAndSalsa(prev, pi, input, ii, out, oi) {
 
-         // Based on https://cr.yp.to/salsa20.html
 
-         // Xor blocks
 
-         let y00 = prev[pi++] ^ input[ii++], y01 = prev[pi++] ^ input[ii++];
 
-         let y02 = prev[pi++] ^ input[ii++], y03 = prev[pi++] ^ input[ii++];
 
-         let y04 = prev[pi++] ^ input[ii++], y05 = prev[pi++] ^ input[ii++];
 
-         let y06 = prev[pi++] ^ input[ii++], y07 = prev[pi++] ^ input[ii++];
 
-         let y08 = prev[pi++] ^ input[ii++], y09 = prev[pi++] ^ input[ii++];
 
-         let y10 = prev[pi++] ^ input[ii++], y11 = prev[pi++] ^ input[ii++];
 
-         let y12 = prev[pi++] ^ input[ii++], y13 = prev[pi++] ^ input[ii++];
 
-         let y14 = prev[pi++] ^ input[ii++], y15 = prev[pi++] ^ input[ii++];
 
-         // Save state to temporary variables (salsa)
 
-         let x00 = y00, x01 = y01, x02 = y02, x03 = y03, x04 = y04, x05 = y05, x06 = y06, x07 = y07, x08 = y08, x09 = y09, x10 = y10, x11 = y11, x12 = y12, x13 = y13, x14 = y14, x15 = y15;
 
-         // Main loop (salsa)
 
-         for (let i = 0; i < 8; i += 2) {
 
-             x04 ^= rotl(x00 + x12 | 0, 7);
 
-             x08 ^= rotl(x04 + x00 | 0, 9);
 
-             x12 ^= rotl(x08 + x04 | 0, 13);
 
-             x00 ^= rotl(x12 + x08 | 0, 18);
 
-             x09 ^= rotl(x05 + x01 | 0, 7);
 
-             x13 ^= rotl(x09 + x05 | 0, 9);
 
-             x01 ^= rotl(x13 + x09 | 0, 13);
 
-             x05 ^= rotl(x01 + x13 | 0, 18);
 
-             x14 ^= rotl(x10 + x06 | 0, 7);
 
-             x02 ^= rotl(x14 + x10 | 0, 9);
 
-             x06 ^= rotl(x02 + x14 | 0, 13);
 
-             x10 ^= rotl(x06 + x02 | 0, 18);
 
-             x03 ^= rotl(x15 + x11 | 0, 7);
 
-             x07 ^= rotl(x03 + x15 | 0, 9);
 
-             x11 ^= rotl(x07 + x03 | 0, 13);
 
-             x15 ^= rotl(x11 + x07 | 0, 18);
 
-             x01 ^= rotl(x00 + x03 | 0, 7);
 
-             x02 ^= rotl(x01 + x00 | 0, 9);
 
-             x03 ^= rotl(x02 + x01 | 0, 13);
 
-             x00 ^= rotl(x03 + x02 | 0, 18);
 
-             x06 ^= rotl(x05 + x04 | 0, 7);
 
-             x07 ^= rotl(x06 + x05 | 0, 9);
 
-             x04 ^= rotl(x07 + x06 | 0, 13);
 
-             x05 ^= rotl(x04 + x07 | 0, 18);
 
-             x11 ^= rotl(x10 + x09 | 0, 7);
 
-             x08 ^= rotl(x11 + x10 | 0, 9);
 
-             x09 ^= rotl(x08 + x11 | 0, 13);
 
-             x10 ^= rotl(x09 + x08 | 0, 18);
 
-             x12 ^= rotl(x15 + x14 | 0, 7);
 
-             x13 ^= rotl(x12 + x15 | 0, 9);
 
-             x14 ^= rotl(x13 + x12 | 0, 13);
 
-             x15 ^= rotl(x14 + x13 | 0, 18);
 
-         }
 
-         // Write output (salsa)
 
-         out[oi++] = (y00 + x00) | 0;
 
-         out[oi++] = (y01 + x01) | 0;
 
-         out[oi++] = (y02 + x02) | 0;
 
-         out[oi++] = (y03 + x03) | 0;
 
-         out[oi++] = (y04 + x04) | 0;
 
-         out[oi++] = (y05 + x05) | 0;
 
-         out[oi++] = (y06 + x06) | 0;
 
-         out[oi++] = (y07 + x07) | 0;
 
-         out[oi++] = (y08 + x08) | 0;
 
-         out[oi++] = (y09 + x09) | 0;
 
-         out[oi++] = (y10 + x10) | 0;
 
-         out[oi++] = (y11 + x11) | 0;
 
-         out[oi++] = (y12 + x12) | 0;
 
-         out[oi++] = (y13 + x13) | 0;
 
-         out[oi++] = (y14 + x14) | 0;
 
-         out[oi++] = (y15 + x15) | 0;
 
-     }
 
-     function BlockMix(input, ii, out, oi, r) {
 
-         // The block B is r 128-byte chunks (which is equivalent of 2r 64-byte chunks)
 
-         let head = oi + 0;
 
-         let tail = oi + 16 * r;
 
-         for (let i = 0; i < 16; i++)
 
-             out[tail + i] = input[ii + (2 * r - 1) * 16 + i]; // X ← B[2r−1]
 
-         for (let i = 0; i < r; i++, head += 16, ii += 16) {
 
-             // We write odd & even Yi at same time. Even: 0bXXXXX0 Odd:  0bXXXXX1
 
-             XorAndSalsa(out, tail, input, ii, out, head); // head[i] = Salsa(blockIn[2*i] ^ tail[i-1])
 
-             if (i > 0)
 
-                 tail += 16; // First iteration overwrites tmp value in tail
 
-             XorAndSalsa(out, head, input, (ii += 16), out, tail); // tail[i] = Salsa(blockIn[2*i+1] ^ head[i])
 
-         }
 
-     }
 
-     // Common prologue and epilogue for sync/async functions
 
-     function scryptInit(password, salt, _opts) {
 
-         // Maxmem - 1GB+1KB by default
 
-         const opts = checkOpts({
 
-             dkLen: 32,
 
-             asyncTick: 10,
 
-             maxmem: 1024 ** 3 + 1024,
 
-         }, _opts);
 
-         const { N, r, p, dkLen, asyncTick, maxmem, onProgress } = opts;
 
-         number(N);
 
-         number(r);
 
-         number(p);
 
-         number(dkLen);
 
-         number(asyncTick);
 
-         number(maxmem);
 
-         if (onProgress !== undefined && typeof onProgress !== 'function')
 
-             throw new Error('progressCb should be function');
 
-         const blockSize = 128 * r;
 
-         const blockSize32 = blockSize / 4;
 
-         if (N <= 1 || (N & (N - 1)) !== 0 || N >= 2 ** (blockSize / 8) || N > 2 ** 32) {
 
-             // NOTE: we limit N to be less than 2**32 because of 32 bit variant of Integrify function
 
-             // There is no JS engines that allows alocate more than 4GB per single Uint8Array for now, but can change in future.
 
-             throw new Error('Scrypt: N must be larger than 1, a power of 2, less than 2^(128 * r / 8) and less than 2^32');
 
-         }
 
-         if (p < 0 || p > ((2 ** 32 - 1) * 32) / blockSize) {
 
-             throw new Error('Scrypt: p must be a positive integer less than or equal to ((2^32 - 1) * 32) / (128 * r)');
 
-         }
 
-         if (dkLen < 0 || dkLen > (2 ** 32 - 1) * 32) {
 
-             throw new Error('Scrypt: dkLen should be positive integer less than or equal to (2^32 - 1) * 32');
 
-         }
 
-         const memUsed = blockSize * (N + p);
 
-         if (memUsed > maxmem) {
 
-             throw new Error(`Scrypt: parameters too large, ${memUsed} (128 * r * (N + p)) > ${maxmem} (maxmem)`);
 
-         }
 
-         // [B0...Bp−1] ← PBKDF2HMAC-SHA256(Passphrase, Salt, 1, blockSize*ParallelizationFactor)
 
-         // Since it has only one iteration there is no reason to use async variant
 
-         const B = pbkdf2$1(sha256$1, password, salt, { c: 1, dkLen: blockSize * p });
 
-         const B32 = u32(B);
 
-         // Re-used between parallel iterations. Array(iterations) of B
 
-         const V = u32(new Uint8Array(blockSize * N));
 
-         const tmp = u32(new Uint8Array(blockSize));
 
-         let blockMixCb = () => { };
 
-         if (onProgress) {
 
-             const totalBlockMix = 2 * N * p;
 
-             // Invoke callback if progress changes from 10.01 to 10.02
 
-             // Allows to draw smooth progress bar on up to 8K screen
 
-             const callbackPer = Math.max(Math.floor(totalBlockMix / 10000), 1);
 
-             let blockMixCnt = 0;
 
-             blockMixCb = () => {
 
-                 blockMixCnt++;
 
-                 if (onProgress && (!(blockMixCnt % callbackPer) || blockMixCnt === totalBlockMix))
 
-                     onProgress(blockMixCnt / totalBlockMix);
 
-             };
 
-         }
 
-         return { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb, asyncTick };
 
-     }
 
-     function scryptOutput(password, dkLen, B, V, tmp) {
 
-         const res = pbkdf2$1(sha256$1, password, B, { c: 1, dkLen });
 
-         B.fill(0);
 
-         V.fill(0);
 
-         tmp.fill(0);
 
-         return res;
 
-     }
 
-     /**
 
-      * Scrypt KDF from RFC 7914.
 
-      * @param password - pass
 
-      * @param salt - salt
 
-      * @param opts - parameters
 
-      * - `N` is cpu/mem work factor (power of 2 e.g. 2**18)
 
-      * - `r` is block size (8 is common), fine-tunes sequential memory read size and performance
 
-      * - `p` is parallelization factor (1 is common)
 
-      * - `dkLen` is output key length in bytes e.g. 32.
 
-      * - `asyncTick` - (default: 10) max time in ms for which async function can block execution
 
-      * - `maxmem` - (default: `1024 ** 3 + 1024` aka 1GB+1KB). A limit that the app could use for scrypt
 
-      * - `onProgress` - callback function that would be executed for progress report
 
-      * @returns Derived key
 
-      */
 
-     function scrypt$1(password, salt, opts) {
 
-         const { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb } = scryptInit(password, salt, opts);
 
-         for (let pi = 0; pi < p; pi++) {
 
-             const Pi = blockSize32 * pi;
 
-             for (let i = 0; i < blockSize32; i++)
 
-                 V[i] = B32[Pi + i]; // V[0] = B[i]
 
-             for (let i = 0, pos = 0; i < N - 1; i++) {
 
-                 BlockMix(V, pos, V, (pos += blockSize32), r); // V[i] = BlockMix(V[i-1]);
 
-                 blockMixCb();
 
-             }
 
-             BlockMix(V, (N - 1) * blockSize32, B32, Pi, r); // Process last element
 
-             blockMixCb();
 
-             for (let i = 0; i < N; i++) {
 
-                 // First u32 of the last 64-byte block (u32 is LE)
 
-                 const j = B32[Pi + blockSize32 - 16] % N; // j = Integrify(X) % iterations
 
-                 for (let k = 0; k < blockSize32; k++)
 
-                     tmp[k] = B32[Pi + k] ^ V[j * blockSize32 + k]; // tmp = B ^ V[j]
 
-                 BlockMix(tmp, 0, B32, Pi, r); // B = BlockMix(B ^ V[j])
 
-                 blockMixCb();
 
-             }
 
-         }
 
-         return scryptOutput(password, dkLen, B, V, tmp);
 
-     }
 
-     /**
 
-      * Scrypt KDF from RFC 7914.
 
-      */
 
-     async function scryptAsync(password, salt, opts) {
 
-         const { N, r, p, dkLen, blockSize32, V, B32, B, tmp, blockMixCb, asyncTick } = scryptInit(password, salt, opts);
 
-         for (let pi = 0; pi < p; pi++) {
 
-             const Pi = blockSize32 * pi;
 
-             for (let i = 0; i < blockSize32; i++)
 
-                 V[i] = B32[Pi + i]; // V[0] = B[i]
 
-             let pos = 0;
 
-             await asyncLoop(N - 1, asyncTick, () => {
 
-                 BlockMix(V, pos, V, (pos += blockSize32), r); // V[i] = BlockMix(V[i-1]);
 
-                 blockMixCb();
 
-             });
 
-             BlockMix(V, (N - 1) * blockSize32, B32, Pi, r); // Process last element
 
-             blockMixCb();
 
-             await asyncLoop(N, asyncTick, () => {
 
-                 // First u32 of the last 64-byte block (u32 is LE)
 
-                 const j = B32[Pi + blockSize32 - 16] % N; // j = Integrify(X) % iterations
 
-                 for (let k = 0; k < blockSize32; k++)
 
-                     tmp[k] = B32[Pi + k] ^ V[j * blockSize32 + k]; // tmp = B ^ V[j]
 
-                 BlockMix(tmp, 0, B32, Pi, r); // B = BlockMix(B ^ V[j])
 
-                 blockMixCb();
 
-             });
 
-         }
 
-         return scryptOutput(password, dkLen, B, V, tmp);
 
-     }
 
-     let lockedSync = false, lockedAsync = false;
 
-     const _scryptAsync = async function (passwd, salt, N, r, p, dkLen, onProgress) {
 
-         return await scryptAsync(passwd, salt, { N, r, p, dkLen, onProgress });
 
-     };
 
-     const _scryptSync = function (passwd, salt, N, r, p, dkLen) {
 
-         return scrypt$1(passwd, salt, { N, r, p, dkLen });
 
-     };
 
-     let __scryptAsync = _scryptAsync;
 
-     let __scryptSync = _scryptSync;
 
-     /**
 
-      *  The [[link-wiki-scrypt]] uses a memory and cpu hard method of
 
-      *  derivation to increase the resource cost to brute-force a password
 
-      *  for a given key.
 
-      *
 
-      *  This means this algorithm is intentionally slow, and can be tuned to
 
-      *  become slower. As computation and memory speed improve over time,
 
-      *  increasing the difficulty maintains the cost of an attacker.
 
-      *
 
-      *  For example, if a target time of 5 seconds is used, a legitimate user
 
-      *  which knows their password requires only 5 seconds to unlock their
 
-      *  account. A 6 character password has 68 billion possibilities, which
 
-      *  would require an attacker to invest over 10,000 years of CPU time. This
 
-      *  is of course a crude example (as password generally aren't random),
 
-      *  but demonstrates to value of imposing large costs to decryption.
 
-      *
 
-      *  For this reason, if building a UI which involved decrypting or
 
-      *  encrypting datsa using scrypt, it is recommended to use a
 
-      *  [[ProgressCallback]] (as event short periods can seem lik an eternity
 
-      *  if the UI freezes). Including the phrase //"decrypting"// in the UI
 
-      *  can also help, assuring the user their waiting is for a good reason.
 
-      *
 
-      *  @_docloc: api/crypto:Passwords
 
-      *
 
-      *  @example:
 
-      *    // The password must be converted to bytes, and it is generally
 
-      *    // best practices to ensure the string has been normalized. Many
 
-      *    // formats explicitly indicate the normalization form to use.
 
-      *    password = "hello"
 
-      *    passwordBytes = toUtf8Bytes(password, "NFKC")
 
-      *
 
-      *    salt = id("some-salt")
 
-      *
 
-      *    // Compute the scrypt
 
-      *    scrypt(passwordBytes, salt, 1024, 8, 1, 16)
 
-      *    //_result:
 
-      */
 
-     async function scrypt(_passwd, _salt, N, r, p, dkLen, progress) {
 
-         const passwd = getBytes(_passwd, "passwd");
 
-         const salt = getBytes(_salt, "salt");
 
-         return hexlify(await __scryptAsync(passwd, salt, N, r, p, dkLen, progress));
 
-     }
 
-     scrypt._ = _scryptAsync;
 
-     scrypt.lock = function () { lockedAsync = true; };
 
-     scrypt.register = function (func) {
 
-         if (lockedAsync) {
 
-             throw new Error("scrypt is locked");
 
-         }
 
-         __scryptAsync = func;
 
-     };
 
-     Object.freeze(scrypt);
 
-     /**
 
-      *  Provides a synchronous variant of [[scrypt]].
 
-      *
 
-      *  This will completely lock up and freeze the UI in a browser and will
 
-      *  prevent any event loop from progressing. For this reason, it is
 
-      *  preferred to use the [async variant](scrypt).
 
-      *
 
-      *  @_docloc: api/crypto:Passwords
 
-      *
 
-      *  @example:
 
-      *    // The password must be converted to bytes, and it is generally
 
-      *    // best practices to ensure the string has been normalized. Many
 
-      *    // formats explicitly indicate the normalization form to use.
 
-      *    password = "hello"
 
-      *    passwordBytes = toUtf8Bytes(password, "NFKC")
 
-      *
 
-      *    salt = id("some-salt")
 
-      *
 
-      *    // Compute the scrypt
 
-      *    scryptSync(passwordBytes, salt, 1024, 8, 1, 16)
 
-      *    //_result:
 
-      */
 
-     function scryptSync(_passwd, _salt, N, r, p, dkLen) {
 
-         const passwd = getBytes(_passwd, "passwd");
 
-         const salt = getBytes(_salt, "salt");
 
-         return hexlify(__scryptSync(passwd, salt, N, r, p, dkLen));
 
-     }
 
-     scryptSync._ = _scryptSync;
 
-     scryptSync.lock = function () { lockedSync = true; };
 
-     scryptSync.register = function (func) {
 
-         if (lockedSync) {
 
-             throw new Error("scryptSync is locked");
 
-         }
 
-         __scryptSync = func;
 
-     };
 
-     Object.freeze(scryptSync);
 
-     const _sha256 = function (data) {
 
-         return createHash("sha256").update(data).digest();
 
-     };
 
-     const _sha512 = function (data) {
 
-         return createHash("sha512").update(data).digest();
 
-     };
 
-     let __sha256 = _sha256;
 
-     let __sha512 = _sha512;
 
-     let locked256 = false, locked512 = false;
 
-     /**
 
-      *  Compute the cryptographic SHA2-256 hash of %%data%%.
 
-      *
 
-      *  @_docloc: api/crypto:Hash Functions
 
-      *  @returns DataHexstring
 
-      *
 
-      *  @example:
 
-      *    sha256("0x")
 
-      *    //_result:
 
-      *
 
-      *    sha256("0x1337")
 
-      *    //_result:
 
-      *
 
-      *    sha256(new Uint8Array([ 0x13, 0x37 ]))
 
-      *    //_result:
 
-      *
 
-      */
 
-     function sha256(_data) {
 
-         const data = getBytes(_data, "data");
 
-         return hexlify(__sha256(data));
 
-     }
 
-     sha256._ = _sha256;
 
-     sha256.lock = function () { locked256 = true; };
 
-     sha256.register = function (func) {
 
-         if (locked256) {
 
-             throw new Error("sha256 is locked");
 
-         }
 
-         __sha256 = func;
 
-     };
 
-     Object.freeze(sha256);
 
-     /**
 
-      *  Compute the cryptographic SHA2-512 hash of %%data%%.
 
-      *
 
-      *  @_docloc: api/crypto:Hash Functions
 
-      *  @returns DataHexstring
 
-      *
 
-      *  @example:
 
-      *    sha512("0x")
 
-      *    //_result:
 
-      *
 
-      *    sha512("0x1337")
 
-      *    //_result:
 
-      *
 
-      *    sha512(new Uint8Array([ 0x13, 0x37 ]))
 
-      *    //_result:
 
-      */
 
-     function sha512(_data) {
 
-         const data = getBytes(_data, "data");
 
-         return hexlify(__sha512(data));
 
-     }
 
-     sha512._ = _sha512;
 
-     sha512.lock = function () { locked512 = true; };
 
-     sha512.register = function (func) {
 
-         if (locked512) {
 
-             throw new Error("sha512 is locked");
 
-         }
 
-         __sha512 = func;
 
-     };
 
-     Object.freeze(sha256);
 
-     /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
 
-     // 100 lines of code in the file are duplicated from noble-hashes (utils).
 
-     // This is OK: `abstract` directory does not use noble-hashes.
 
-     // User may opt-in into using different hashing library. This way, noble-hashes
 
-     // won't be included into their bundle.
 
-     const _0n$3 = BigInt(0);
 
-     const _1n$4 = BigInt(1);
 
-     const _2n$2 = BigInt(2);
 
-     const u8a = (a) => a instanceof Uint8Array;
 
-     const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
 
-     /**
 
-      * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'
 
-      */
 
-     function bytesToHex(bytes) {
 
-         if (!u8a(bytes))
 
-             throw new Error('Uint8Array expected');
 
-         // pre-caching improves the speed 6x
 
-         let hex = '';
 
-         for (let i = 0; i < bytes.length; i++) {
 
-             hex += hexes[bytes[i]];
 
-         }
 
-         return hex;
 
-     }
 
-     function numberToHexUnpadded(num) {
 
-         const hex = num.toString(16);
 
-         return hex.length & 1 ? `0${hex}` : hex;
 
-     }
 
-     function hexToNumber(hex) {
 
-         if (typeof hex !== 'string')
 
-             throw new Error('hex string expected, got ' + typeof hex);
 
-         // Big Endian
 
-         return BigInt(hex === '' ? '0' : `0x${hex}`);
 
-     }
 
-     /**
 
-      * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])
 
-      */
 
-     function hexToBytes(hex) {
 
-         if (typeof hex !== 'string')
 
-             throw new Error('hex string expected, got ' + typeof hex);
 
-         const len = hex.length;
 
-         if (len % 2)
 
-             throw new Error('padded hex string expected, got unpadded hex of length ' + len);
 
-         const array = new Uint8Array(len / 2);
 
-         for (let i = 0; i < array.length; i++) {
 
-             const j = i * 2;
 
-             const hexByte = hex.slice(j, j + 2);
 
-             const byte = Number.parseInt(hexByte, 16);
 
-             if (Number.isNaN(byte) || byte < 0)
 
-                 throw new Error('Invalid byte sequence');
 
-             array[i] = byte;
 
-         }
 
-         return array;
 
-     }
 
-     // BE: Big Endian, LE: Little Endian
 
-     function bytesToNumberBE(bytes) {
 
-         return hexToNumber(bytesToHex(bytes));
 
-     }
 
-     function bytesToNumberLE(bytes) {
 
-         if (!u8a(bytes))
 
-             throw new Error('Uint8Array expected');
 
-         return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
 
-     }
 
-     function numberToBytesBE(n, len) {
 
-         return hexToBytes(n.toString(16).padStart(len * 2, '0'));
 
-     }
 
-     function numberToBytesLE(n, len) {
 
-         return numberToBytesBE(n, len).reverse();
 
-     }
 
-     // Unpadded, rarely used
 
-     function numberToVarBytesBE(n) {
 
-         return hexToBytes(numberToHexUnpadded(n));
 
-     }
 
-     /**
 
-      * Takes hex string or Uint8Array, converts to Uint8Array.
 
-      * Validates output length.
 
-      * Will throw error for other types.
 
-      * @param title descriptive title for an error e.g. 'private key'
 
-      * @param hex hex string or Uint8Array
 
-      * @param expectedLength optional, will compare to result array's length
 
-      * @returns
 
-      */
 
-     function ensureBytes(title, hex, expectedLength) {
 
-         let res;
 
-         if (typeof hex === 'string') {
 
-             try {
 
-                 res = hexToBytes(hex);
 
-             }
 
-             catch (e) {
 
-                 throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);
 
-             }
 
-         }
 
-         else if (u8a(hex)) {
 
-             // Uint8Array.from() instead of hash.slice() because node.js Buffer
 
-             // is instance of Uint8Array, and its slice() creates **mutable** copy
 
-             res = Uint8Array.from(hex);
 
-         }
 
-         else {
 
-             throw new Error(`${title} must be hex string or Uint8Array`);
 
-         }
 
-         const len = res.length;
 
-         if (typeof expectedLength === 'number' && len !== expectedLength)
 
-             throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
 
-         return res;
 
-     }
 
-     /**
 
-      * Copies several Uint8Arrays into one.
 
-      */
 
-     function concatBytes(...arrays) {
 
-         const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));
 
-         let pad = 0; // walk through each item, ensure they have proper type
 
-         arrays.forEach((a) => {
 
-             if (!u8a(a))
 
-                 throw new Error('Uint8Array expected');
 
-             r.set(a, pad);
 
-             pad += a.length;
 
-         });
 
-         return r;
 
-     }
 
-     function equalBytes(b1, b2) {
 
-         // We don't care about timing attacks here
 
-         if (b1.length !== b2.length)
 
-             return false;
 
-         for (let i = 0; i < b1.length; i++)
 
-             if (b1[i] !== b2[i])
 
-                 return false;
 
-         return true;
 
-     }
 
-     /**
 
-      * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
 
-      */
 
-     function utf8ToBytes(str) {
 
-         if (typeof str !== 'string')
 
-             throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
 
-         return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
 
-     }
 
-     // Bit operations
 
-     /**
 
-      * Calculates amount of bits in a bigint.
 
-      * Same as `n.toString(2).length`
 
-      */
 
-     function bitLen(n) {
 
-         let len;
 
-         for (len = 0; n > _0n$3; n >>= _1n$4, len += 1)
 
-             ;
 
-         return len;
 
-     }
 
-     /**
 
-      * Gets single bit at position.
 
-      * NOTE: first bit position is 0 (same as arrays)
 
-      * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`
 
-      */
 
-     function bitGet(n, pos) {
 
-         return (n >> BigInt(pos)) & _1n$4;
 
-     }
 
-     /**
 
-      * Sets single bit at position.
 
-      */
 
-     const bitSet = (n, pos, value) => {
 
-         return n | ((value ? _1n$4 : _0n$3) << BigInt(pos));
 
-     };
 
-     /**
 
-      * Calculate mask for N bits. Not using ** operator with bigints because of old engines.
 
-      * Same as BigInt(`0b${Array(i).fill('1').join('')}`)
 
-      */
 
-     const bitMask = (n) => (_2n$2 << BigInt(n - 1)) - _1n$4;
 
-     // DRBG
 
-     const u8n = (data) => new Uint8Array(data); // creates Uint8Array
 
-     const u8fr = (arr) => Uint8Array.from(arr); // another shortcut
 
-     /**
 
-      * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
 
-      * @returns function that will call DRBG until 2nd arg returns something meaningful
 
-      * @example
 
-      *   const drbg = createHmacDRBG<Key>(32, 32, hmac);
 
-      *   drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
 
-      */
 
-     function createHmacDrbg(hashLen, qByteLen, hmacFn) {
 
-         if (typeof hashLen !== 'number' || hashLen < 2)
 
-             throw new Error('hashLen must be a number');
 
-         if (typeof qByteLen !== 'number' || qByteLen < 2)
 
-             throw new Error('qByteLen must be a number');
 
-         if (typeof hmacFn !== 'function')
 
-             throw new Error('hmacFn must be a function');
 
-         // Step B, Step C: set hashLen to 8*ceil(hlen/8)
 
-         let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
 
-         let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
 
-         let i = 0; // Iterations counter, will throw when over 1000
 
-         const reset = () => {
 
-             v.fill(1);
 
-             k.fill(0);
 
-             i = 0;
 
-         };
 
-         const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
 
-         const reseed = (seed = u8n()) => {
 
-             // HMAC-DRBG reseed() function. Steps D-G
 
-             k = h(u8fr([0x00]), seed); // k = hmac(k || v || 0x00 || seed)
 
-             v = h(); // v = hmac(k || v)
 
-             if (seed.length === 0)
 
-                 return;
 
-             k = h(u8fr([0x01]), seed); // k = hmac(k || v || 0x01 || seed)
 
-             v = h(); // v = hmac(k || v)
 
-         };
 
-         const gen = () => {
 
-             // HMAC-DRBG generate() function
 
-             if (i++ >= 1000)
 
-                 throw new Error('drbg: tried 1000 values');
 
-             let len = 0;
 
-             const out = [];
 
-             while (len < qByteLen) {
 
-                 v = h();
 
-                 const sl = v.slice();
 
-                 out.push(sl);
 
-                 len += v.length;
 
-             }
 
-             return concatBytes(...out);
 
-         };
 
-         const genUntil = (seed, pred) => {
 
-             reset();
 
-             reseed(seed); // Steps D-G
 
-             let res = undefined; // Step H: grind until k is in [1..n-1]
 
-             while (!(res = pred(gen())))
 
-                 reseed();
 
-             reset();
 
-             return res;
 
-         };
 
-         return genUntil;
 
-     }
 
-     // Validating curves and fields
 
-     const validatorFns = {
 
-         bigint: (val) => typeof val === 'bigint',
 
-         function: (val) => typeof val === 'function',
 
-         boolean: (val) => typeof val === 'boolean',
 
-         string: (val) => typeof val === 'string',
 
-         stringOrUint8Array: (val) => typeof val === 'string' || val instanceof Uint8Array,
 
-         isSafeInteger: (val) => Number.isSafeInteger(val),
 
-         array: (val) => Array.isArray(val),
 
-         field: (val, object) => object.Fp.isValid(val),
 
-         hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen),
 
-     };
 
-     // type Record<K extends string | number | symbol, T> = { [P in K]: T; }
 
-     function validateObject(object, validators, optValidators = {}) {
 
-         const checkField = (fieldName, type, isOptional) => {
 
-             const checkVal = validatorFns[type];
 
-             if (typeof checkVal !== 'function')
 
-                 throw new Error(`Invalid validator "${type}", expected function`);
 
-             const val = object[fieldName];
 
-             if (isOptional && val === undefined)
 
-                 return;
 
-             if (!checkVal(val, object)) {
 
-                 throw new Error(`Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`);
 
-             }
 
-         };
 
-         for (const [fieldName, type] of Object.entries(validators))
 
-             checkField(fieldName, type, false);
 
-         for (const [fieldName, type] of Object.entries(optValidators))
 
-             checkField(fieldName, type, true);
 
-         return object;
 
-     }
 
-     // validate type tests
 
-     // const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 };
 
-     // const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok!
 
-     // // Should fail type-check
 
-     // const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' });
 
-     // const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' });
 
-     // const z3 = validateObject(o, { test: 'boolean', z: 'bug' });
 
-     // const z4 = validateObject(o, { a: 'boolean', z: 'bug' });
 
-     var ut = /*#__PURE__*/Object.freeze({
 
-         __proto__: null,
 
-         bitGet: bitGet,
 
-         bitLen: bitLen,
 
-         bitMask: bitMask,
 
-         bitSet: bitSet,
 
-         bytesToHex: bytesToHex,
 
-         bytesToNumberBE: bytesToNumberBE,
 
-         bytesToNumberLE: bytesToNumberLE,
 
-         concatBytes: concatBytes,
 
-         createHmacDrbg: createHmacDrbg,
 
-         ensureBytes: ensureBytes,
 
-         equalBytes: equalBytes,
 
-         hexToBytes: hexToBytes,
 
-         hexToNumber: hexToNumber,
 
-         numberToBytesBE: numberToBytesBE,
 
-         numberToBytesLE: numberToBytesLE,
 
-         numberToHexUnpadded: numberToHexUnpadded,
 
-         numberToVarBytesBE: numberToVarBytesBE,
 
-         utf8ToBytes: utf8ToBytes,
 
-         validateObject: validateObject
 
-     });
 
-     /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
 
-     // Utilities for modular arithmetics and finite fields
 
-     // prettier-ignore
 
-     const _0n$2 = BigInt(0), _1n$3 = BigInt(1), _2n$1 = BigInt(2), _3n$1 = BigInt(3);
 
-     // prettier-ignore
 
-     const _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
 
-     // prettier-ignore
 
-     BigInt(9); BigInt(16);
 
-     // Calculates a modulo b
 
-     function mod(a, b) {
 
-         const result = a % b;
 
-         return result >= _0n$2 ? result : b + result;
 
-     }
 
-     /**
 
-      * Efficiently raise num to power and do modular division.
 
-      * Unsafe in some contexts: uses ladder, so can expose bigint bits.
 
-      * @example
 
-      * pow(2n, 6n, 11n) // 64n % 11n == 9n
 
-      */
 
-     // TODO: use field version && remove
 
-     function pow(num, power, modulo) {
 
-         if (modulo <= _0n$2 || power < _0n$2)
 
-             throw new Error('Expected power/modulo > 0');
 
-         if (modulo === _1n$3)
 
-             return _0n$2;
 
-         let res = _1n$3;
 
-         while (power > _0n$2) {
 
-             if (power & _1n$3)
 
-                 res = (res * num) % modulo;
 
-             num = (num * num) % modulo;
 
-             power >>= _1n$3;
 
-         }
 
-         return res;
 
-     }
 
-     // Does x ^ (2 ^ power) mod p. pow2(30, 4) == 30 ^ (2 ^ 4)
 
-     function pow2(x, power, modulo) {
 
-         let res = x;
 
-         while (power-- > _0n$2) {
 
-             res *= res;
 
-             res %= modulo;
 
-         }
 
-         return res;
 
-     }
 
-     // Inverses number over modulo
 
-     function invert(number, modulo) {
 
-         if (number === _0n$2 || modulo <= _0n$2) {
 
-             throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
 
-         }
 
-         // Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
 
-         // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
 
-         let a = mod(number, modulo);
 
-         let b = modulo;
 
-         // prettier-ignore
 
-         let x = _0n$2, u = _1n$3;
 
-         while (a !== _0n$2) {
 
-             // JIT applies optimization if those two lines follow each other
 
-             const q = b / a;
 
-             const r = b % a;
 
-             const m = x - u * q;
 
-             // prettier-ignore
 
-             b = a, a = r, x = u, u = m;
 
-         }
 
-         const gcd = b;
 
-         if (gcd !== _1n$3)
 
-             throw new Error('invert: does not exist');
 
-         return mod(x, modulo);
 
-     }
 
-     /**
 
-      * Tonelli-Shanks square root search algorithm.
 
-      * 1. https://eprint.iacr.org/2012/685.pdf (page 12)
 
-      * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks
 
-      * Will start an infinite loop if field order P is not prime.
 
-      * @param P field order
 
-      * @returns function that takes field Fp (created from P) and number n
 
-      */
 
-     function tonelliShanks(P) {
 
-         // Legendre constant: used to calculate Legendre symbol (a | p),
 
-         // which denotes the value of a^((p-1)/2) (mod p).
 
-         // (a | p) ≡ 1    if a is a square (mod p)
 
-         // (a | p) ≡ -1   if a is not a square (mod p)
 
-         // (a | p) ≡ 0    if a ≡ 0 (mod p)
 
-         const legendreC = (P - _1n$3) / _2n$1;
 
-         let Q, S, Z;
 
-         // Step 1: By factoring out powers of 2 from p - 1,
 
-         // find q and s such that p - 1 = q*(2^s) with q odd
 
-         for (Q = P - _1n$3, S = 0; Q % _2n$1 === _0n$2; Q /= _2n$1, S++)
 
-             ;
 
-         // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
 
-         for (Z = _2n$1; Z < P && pow(Z, legendreC, P) !== P - _1n$3; Z++)
 
-             ;
 
-         // Fast-path
 
-         if (S === 1) {
 
-             const p1div4 = (P + _1n$3) / _4n;
 
-             return function tonelliFast(Fp, n) {
 
-                 const root = Fp.pow(n, p1div4);
 
-                 if (!Fp.eql(Fp.sqr(root), n))
 
-                     throw new Error('Cannot find square root');
 
-                 return root;
 
-             };
 
-         }
 
-         // Slow-path
 
-         const Q1div2 = (Q + _1n$3) / _2n$1;
 
-         return function tonelliSlow(Fp, n) {
 
-             // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1
 
-             if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE))
 
-                 throw new Error('Cannot find square root');
 
-             let r = S;
 
-             // TODO: will fail at Fp2/etc
 
-             let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q); // will update both x and b
 
-             let x = Fp.pow(n, Q1div2); // first guess at the square root
 
-             let b = Fp.pow(n, Q); // first guess at the fudge factor
 
-             while (!Fp.eql(b, Fp.ONE)) {
 
-                 if (Fp.eql(b, Fp.ZERO))
 
-                     return Fp.ZERO; // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0)
 
-                 // Find m such b^(2^m)==1
 
-                 let m = 1;
 
-                 for (let t2 = Fp.sqr(b); m < r; m++) {
 
-                     if (Fp.eql(t2, Fp.ONE))
 
-                         break;
 
-                     t2 = Fp.sqr(t2); // t2 *= t2
 
-                 }
 
-                 // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow
 
-                 const ge = Fp.pow(g, _1n$3 << BigInt(r - m - 1)); // ge = 2^(r-m-1)
 
-                 g = Fp.sqr(ge); // g = ge * ge
 
-                 x = Fp.mul(x, ge); // x *= ge
 
-                 b = Fp.mul(b, g); // b *= g
 
-                 r = m;
 
-             }
 
-             return x;
 
-         };
 
-     }
 
-     function FpSqrt(P) {
 
-         // NOTE: different algorithms can give different roots, it is up to user to decide which one they want.
 
-         // For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
 
-         // P ≡ 3 (mod 4)
 
-         // √n = n^((P+1)/4)
 
-         if (P % _4n === _3n$1) {
 
-             // Not all roots possible!
 
-             // const ORDER =
 
-             //   0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
 
-             // const NUM = 72057594037927816n;
 
-             const p1div4 = (P + _1n$3) / _4n;
 
-             return function sqrt3mod4(Fp, n) {
 
-                 const root = Fp.pow(n, p1div4);
 
-                 // Throw if root**2 != n
 
-                 if (!Fp.eql(Fp.sqr(root), n))
 
-                     throw new Error('Cannot find square root');
 
-                 return root;
 
-             };
 
-         }
 
-         // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)
 
-         if (P % _8n === _5n) {
 
-             const c1 = (P - _5n) / _8n;
 
-             return function sqrt5mod8(Fp, n) {
 
-                 const n2 = Fp.mul(n, _2n$1);
 
-                 const v = Fp.pow(n2, c1);
 
-                 const nv = Fp.mul(n, v);
 
-                 const i = Fp.mul(Fp.mul(nv, _2n$1), v);
 
-                 const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
 
-                 if (!Fp.eql(Fp.sqr(root), n))
 
-                     throw new Error('Cannot find square root');
 
-                 return root;
 
-             };
 
-         }
 
-         // Other cases: Tonelli-Shanks algorithm
 
-         return tonelliShanks(P);
 
-     }
 
-     // prettier-ignore
 
-     const FIELD_FIELDS = [
 
-         'create', 'isValid', 'is0', 'neg', 'inv', 'sqrt', 'sqr',
 
-         'eql', 'add', 'sub', 'mul', 'pow', 'div',
 
-         'addN', 'subN', 'mulN', 'sqrN'
 
-     ];
 
-     function validateField(field) {
 
-         const initial = {
 
-             ORDER: 'bigint',
 
-             MASK: 'bigint',
 
-             BYTES: 'isSafeInteger',
 
-             BITS: 'isSafeInteger',
 
-         };
 
-         const opts = FIELD_FIELDS.reduce((map, val) => {
 
-             map[val] = 'function';
 
-             return map;
 
-         }, initial);
 
-         return validateObject(field, opts);
 
-     }
 
-     // Generic field functions
 
-     /**
 
-      * Same as `pow` but for Fp: non-constant-time.
 
-      * Unsafe in some contexts: uses ladder, so can expose bigint bits.
 
-      */
 
-     function FpPow(f, num, power) {
 
-         // Should have same speed as pow for bigints
 
-         // TODO: benchmark!
 
-         if (power < _0n$2)
 
-             throw new Error('Expected power > 0');
 
-         if (power === _0n$2)
 
-             return f.ONE;
 
-         if (power === _1n$3)
 
-             return num;
 
-         let p = f.ONE;
 
-         let d = num;
 
-         while (power > _0n$2) {
 
-             if (power & _1n$3)
 
-                 p = f.mul(p, d);
 
-             d = f.sqr(d);
 
-             power >>= _1n$3;
 
-         }
 
-         return p;
 
-     }
 
-     /**
 
-      * Efficiently invert an array of Field elements.
 
-      * `inv(0)` will return `undefined` here: make sure to throw an error.
 
-      */
 
-     function FpInvertBatch(f, nums) {
 
-         const tmp = new Array(nums.length);
 
-         // Walk from first to last, multiply them by each other MOD p
 
-         const lastMultiplied = nums.reduce((acc, num, i) => {
 
-             if (f.is0(num))
 
-                 return acc;
 
-             tmp[i] = acc;
 
-             return f.mul(acc, num);
 
-         }, f.ONE);
 
-         // Invert last element
 
-         const inverted = f.inv(lastMultiplied);
 
-         // Walk from last to first, multiply them by inverted each other MOD p
 
-         nums.reduceRight((acc, num, i) => {
 
-             if (f.is0(num))
 
-                 return acc;
 
-             tmp[i] = f.mul(acc, tmp[i]);
 
-             return f.mul(acc, num);
 
-         }, inverted);
 
-         return tmp;
 
-     }
 
-     // CURVE.n lengths
 
-     function nLength(n, nBitLength) {
 
-         // Bit size, byte size of CURVE.n
 
-         const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length;
 
-         const nByteLength = Math.ceil(_nBitLength / 8);
 
-         return { nBitLength: _nBitLength, nByteLength };
 
-     }
 
-     /**
 
-      * Initializes a finite field over prime. **Non-primes are not supported.**
 
-      * Do not init in loop: slow. Very fragile: always run a benchmark on a change.
 
-      * Major performance optimizations:
 
-      * * a) denormalized operations like mulN instead of mul
 
-      * * b) same object shape: never add or remove keys
 
-      * * c) Object.freeze
 
-      * @param ORDER prime positive bigint
 
-      * @param bitLen how many bits the field consumes
 
-      * @param isLE (def: false) if encoding / decoding should be in little-endian
 
-      * @param redef optional faster redefinitions of sqrt and other methods
 
-      */
 
-     function Field(ORDER, bitLen, isLE = false, redef = {}) {
 
-         if (ORDER <= _0n$2)
 
-             throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);
 
-         const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);
 
-         if (BYTES > 2048)
 
-             throw new Error('Field lengths over 2048 bytes are not supported');
 
-         const sqrtP = FpSqrt(ORDER);
 
-         const f = Object.freeze({
 
-             ORDER,
 
-             BITS,
 
-             BYTES,
 
-             MASK: bitMask(BITS),
 
-             ZERO: _0n$2,
 
-             ONE: _1n$3,
 
-             create: (num) => mod(num, ORDER),
 
-             isValid: (num) => {
 
-                 if (typeof num !== 'bigint')
 
-                     throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
 
-                 return _0n$2 <= num && num < ORDER; // 0 is valid element, but it's not invertible
 
-             },
 
-             is0: (num) => num === _0n$2,
 
-             isOdd: (num) => (num & _1n$3) === _1n$3,
 
-             neg: (num) => mod(-num, ORDER),
 
-             eql: (lhs, rhs) => lhs === rhs,
 
-             sqr: (num) => mod(num * num, ORDER),
 
-             add: (lhs, rhs) => mod(lhs + rhs, ORDER),
 
-             sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
 
-             mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
 
-             pow: (num, power) => FpPow(f, num, power),
 
-             div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
 
-             // Same as above, but doesn't normalize
 
-             sqrN: (num) => num * num,
 
-             addN: (lhs, rhs) => lhs + rhs,
 
-             subN: (lhs, rhs) => lhs - rhs,
 
-             mulN: (lhs, rhs) => lhs * rhs,
 
-             inv: (num) => invert(num, ORDER),
 
-             sqrt: redef.sqrt || ((n) => sqrtP(f, n)),
 
-             invertBatch: (lst) => FpInvertBatch(f, lst),
 
-             // TODO: do we really need constant cmov?
 
-             // We don't have const-time bigints anyway, so probably will be not very useful
 
-             cmov: (a, b, c) => (c ? b : a),
 
-             toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
 
-             fromBytes: (bytes) => {
 
-                 if (bytes.length !== BYTES)
 
-                     throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);
 
-                 return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
 
-             },
 
-         });
 
-         return Object.freeze(f);
 
-     }
 
-     /**
 
-      * Returns total number of bytes consumed by the field element.
 
-      * For example, 32 bytes for usual 256-bit weierstrass curve.
 
-      * @param fieldOrder number of field elements, usually CURVE.n
 
-      * @returns byte length of field
 
-      */
 
-     function getFieldBytesLength(fieldOrder) {
 
-         if (typeof fieldOrder !== 'bigint')
 
-             throw new Error('field order must be bigint');
 
-         const bitLength = fieldOrder.toString(2).length;
 
-         return Math.ceil(bitLength / 8);
 
-     }
 
-     /**
 
-      * Returns minimal amount of bytes that can be safely reduced
 
-      * by field order.
 
-      * Should be 2^-128 for 128-bit curve such as P256.
 
-      * @param fieldOrder number of field elements, usually CURVE.n
 
-      * @returns byte length of target hash
 
-      */
 
-     function getMinHashLength(fieldOrder) {
 
-         const length = getFieldBytesLength(fieldOrder);
 
-         return length + Math.ceil(length / 2);
 
-     }
 
-     /**
 
-      * "Constant-time" private key generation utility.
 
-      * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF
 
-      * and convert them into private scalar, with the modulo bias being negligible.
 
-      * Needs at least 48 bytes of input for 32-byte private key.
 
-      * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/
 
-      * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
 
-      * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
 
-      * @param hash hash output from SHA3 or a similar function
 
-      * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)
 
-      * @param isLE interpret hash bytes as LE num
 
-      * @returns valid private scalar
 
-      */
 
-     function mapHashToField(key, fieldOrder, isLE = false) {
 
-         const len = key.length;
 
-         const fieldLen = getFieldBytesLength(fieldOrder);
 
-         const minLen = getMinHashLength(fieldOrder);
 
-         // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
 
-         if (len < 16 || len < minLen || len > 1024)
 
-             throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);
 
-         const num = isLE ? bytesToNumberBE(key) : bytesToNumberLE(key);
 
-         // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
 
-         const reduced = mod(num, fieldOrder - _1n$3) + _1n$3;
 
-         return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
 
-     }
 
-     /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
 
-     // Abelian group utilities
 
-     const _0n$1 = BigInt(0);
 
-     const _1n$2 = BigInt(1);
 
-     // Elliptic curve multiplication of Point by scalar. Fragile.
 
-     // Scalars should always be less than curve order: this should be checked inside of a curve itself.
 
-     // Creates precomputation tables for fast multiplication:
 
-     // - private scalar is split by fixed size windows of W bits
 
-     // - every window point is collected from window's table & added to accumulator
 
-     // - since windows are different, same point inside tables won't be accessed more than once per calc
 
-     // - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
 
-     // - +1 window is neccessary for wNAF
 
-     // - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
 
-     // TODO: Research returning 2d JS array of windows, instead of a single window. This would allow
 
-     // windows to be in different memory locations
 
-     function wNAF(c, bits) {
 
-         const constTimeNegate = (condition, item) => {
 
-             const neg = item.negate();
 
-             return condition ? neg : item;
 
-         };
 
-         const opts = (W) => {
 
-             const windows = Math.ceil(bits / W) + 1; // +1, because
 
-             const windowSize = 2 ** (W - 1); // -1 because we skip zero
 
-             return { windows, windowSize };
 
-         };
 
-         return {
 
-             constTimeNegate,
 
-             // non-const time multiplication ladder
 
-             unsafeLadder(elm, n) {
 
-                 let p = c.ZERO;
 
-                 let d = elm;
 
-                 while (n > _0n$1) {
 
-                     if (n & _1n$2)
 
-                         p = p.add(d);
 
-                     d = d.double();
 
-                     n >>= _1n$2;
 
-                 }
 
-                 return p;
 
-             },
 
-             /**
 
-              * Creates a wNAF precomputation window. Used for caching.
 
-              * Default window size is set by `utils.precompute()` and is equal to 8.
 
-              * Number of precomputed points depends on the curve size:
 
-              * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
 
-              * - 𝑊 is the window size
 
-              * - 𝑛 is the bitlength of the curve order.
 
-              * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
 
-              * @returns precomputed point tables flattened to a single array
 
-              */
 
-             precomputeWindow(elm, W) {
 
-                 const { windows, windowSize } = opts(W);
 
-                 const points = [];
 
-                 let p = elm;
 
-                 let base = p;
 
-                 for (let window = 0; window < windows; window++) {
 
-                     base = p;
 
-                     points.push(base);
 
-                     // =1, because we skip zero
 
-                     for (let i = 1; i < windowSize; i++) {
 
-                         base = base.add(p);
 
-                         points.push(base);
 
-                     }
 
-                     p = base.double();
 
-                 }
 
-                 return points;
 
-             },
 
-             /**
 
-              * Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
 
-              * @param W window size
 
-              * @param precomputes precomputed tables
 
-              * @param n scalar (we don't check here, but should be less than curve order)
 
-              * @returns real and fake (for const-time) points
 
-              */
 
-             wNAF(W, precomputes, n) {
 
-                 // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise
 
-                 // But need to carefully remove other checks before wNAF. ORDER == bits here
 
-                 const { windows, windowSize } = opts(W);
 
-                 let p = c.ZERO;
 
-                 let f = c.BASE;
 
-                 const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.
 
-                 const maxNumber = 2 ** W;
 
-                 const shiftBy = BigInt(W);
 
-                 for (let window = 0; window < windows; window++) {
 
-                     const offset = window * windowSize;
 
-                     // Extract W bits.
 
-                     let wbits = Number(n & mask);
 
-                     // Shift number by W bits.
 
-                     n >>= shiftBy;
 
-                     // If the bits are bigger than max size, we'll split those.
 
-                     // +224 => 256 - 32
 
-                     if (wbits > windowSize) {
 
-                         wbits -= maxNumber;
 
-                         n += _1n$2;
 
-                     }
 
-                     // This code was first written with assumption that 'f' and 'p' will never be infinity point:
 
-                     // since each addition is multiplied by 2 ** W, it cannot cancel each other. However,
 
-                     // there is negate now: it is possible that negated element from low value
 
-                     // would be the same as high element, which will create carry into next window.
 
-                     // It's not obvious how this can fail, but still worth investigating later.
 
-                     // Check if we're onto Zero point.
 
-                     // Add random point inside current window to f.
 
-                     const offset1 = offset;
 
-                     const offset2 = offset + Math.abs(wbits) - 1; // -1 because we skip zero
 
-                     const cond1 = window % 2 !== 0;
 
-                     const cond2 = wbits < 0;
 
-                     if (wbits === 0) {
 
-                         // The most important part for const-time getPublicKey
 
-                         f = f.add(constTimeNegate(cond1, precomputes[offset1]));
 
-                     }
 
-                     else {
 
-                         p = p.add(constTimeNegate(cond2, precomputes[offset2]));
 
-                     }
 
-                 }
 
-                 // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ()
 
-                 // Even if the variable is still unused, there are some checks which will
 
-                 // throw an exception, so compiler needs to prove they won't happen, which is hard.
 
-                 // At this point there is a way to F be infinity-point even if p is not,
 
-                 // which makes it less const-time: around 1 bigint multiply.
 
-                 return { p, f };
 
-             },
 
-             wNAFCached(P, precomputesMap, n, transform) {
 
-                 // @ts-ignore
 
-                 const W = P._WINDOW_SIZE || 1;
 
-                 // Calculate precomputes on a first run, reuse them after
 
-                 let comp = precomputesMap.get(P);
 
-                 if (!comp) {
 
-                     comp = this.precomputeWindow(P, W);
 
-                     if (W !== 1) {
 
-                         precomputesMap.set(P, transform(comp));
 
-                     }
 
-                 }
 
-                 return this.wNAF(W, comp, n);
 
-             },
 
-         };
 
-     }
 
-     function validateBasic(curve) {
 
-         validateField(curve.Fp);
 
-         validateObject(curve, {
 
-             n: 'bigint',
 
-             h: 'bigint',
 
-             Gx: 'field',
 
-             Gy: 'field',
 
-         }, {
 
-             nBitLength: 'isSafeInteger',
 
-             nByteLength: 'isSafeInteger',
 
-         });
 
-         // Set defaults
 
-         return Object.freeze({
 
-             ...nLength(curve.n, curve.nBitLength),
 
-             ...curve,
 
-             ...{ p: curve.Fp.ORDER },
 
-         });
 
-     }
 
-     /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
 
-     // Short Weierstrass curve. The formula is: y² = x³ + ax + b
 
-     function validatePointOpts(curve) {
 
-         const opts = validateBasic(curve);
 
-         validateObject(opts, {
 
-             a: 'field',
 
-             b: 'field',
 
-         }, {
 
-             allowedPrivateKeyLengths: 'array',
 
-             wrapPrivateKey: 'boolean',
 
-             isTorsionFree: 'function',
 
-             clearCofactor: 'function',
 
-             allowInfinityPoint: 'boolean',
 
-             fromBytes: 'function',
 
-             toBytes: 'function',
 
-         });
 
-         const { endo, Fp, a } = opts;
 
-         if (endo) {
 
-             if (!Fp.eql(a, Fp.ZERO)) {
 
-                 throw new Error('Endomorphism can only be defined for Koblitz curves that have a=0');
 
-             }
 
-             if (typeof endo !== 'object' ||
 
-                 typeof endo.beta !== 'bigint' ||
 
-                 typeof endo.splitScalar !== 'function') {
 
-                 throw new Error('Expected endomorphism with beta: bigint and splitScalar: function');
 
-             }
 
-         }
 
-         return Object.freeze({ ...opts });
 
-     }
 
-     // ASN.1 DER encoding utilities
 
-     const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
 
-     const DER = {
 
-         // asn.1 DER encoding utils
 
-         Err: class DERErr extends Error {
 
-             constructor(m = '') {
 
-                 super(m);
 
-             }
 
-         },
 
-         _parseInt(data) {
 
-             const { Err: E } = DER;
 
-             if (data.length < 2 || data[0] !== 0x02)
 
-                 throw new E('Invalid signature integer tag');
 
-             const len = data[1];
 
-             const res = data.subarray(2, len + 2);
 
-             if (!len || res.length !== len)
 
-                 throw new E('Invalid signature integer: wrong length');
 
-             // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
 
-             // since we always use positive integers here. It must always be empty:
 
-             // - add zero byte if exists
 
-             // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
 
-             if (res[0] & 0b10000000)
 
-                 throw new E('Invalid signature integer: negative');
 
-             if (res[0] === 0x00 && !(res[1] & 0b10000000))
 
-                 throw new E('Invalid signature integer: unnecessary leading zero');
 
-             return { d: b2n(res), l: data.subarray(len + 2) }; // d is data, l is left
 
-         },
 
-         toSig(hex) {
 
-             // parse DER signature
 
-             const { Err: E } = DER;
 
-             const data = typeof hex === 'string' ? h2b(hex) : hex;
 
-             if (!(data instanceof Uint8Array))
 
-                 throw new Error('ui8a expected');
 
-             let l = data.length;
 
-             if (l < 2 || data[0] != 0x30)
 
-                 throw new E('Invalid signature tag');
 
-             if (data[1] !== l - 2)
 
-                 throw new E('Invalid signature: incorrect length');
 
-             const { d: r, l: sBytes } = DER._parseInt(data.subarray(2));
 
-             const { d: s, l: rBytesLeft } = DER._parseInt(sBytes);
 
-             if (rBytesLeft.length)
 
-                 throw new E('Invalid signature: left bytes after parsing');
 
-             return { r, s };
 
-         },
 
-         hexFromSig(sig) {
 
-             // Add leading zero if first byte has negative bit enabled. More details in '_parseInt'
 
-             const slice = (s) => (Number.parseInt(s[0], 16) & 0b1000 ? '00' + s : s);
 
-             const h = (num) => {
 
-                 const hex = num.toString(16);
 
-                 return hex.length & 1 ? `0${hex}` : hex;
 
-             };
 
-             const s = slice(h(sig.s));
 
-             const r = slice(h(sig.r));
 
-             const shl = s.length / 2;
 
-             const rhl = r.length / 2;
 
-             const sl = h(shl);
 
-             const rl = h(rhl);
 
-             return `30${h(rhl + shl + 4)}02${rl}${r}02${sl}${s}`;
 
-         },
 
-     };
 
-     // Be friendly to bad ECMAScript parsers by not using bigint literals
 
-     // prettier-ignore
 
-     const _0n = BigInt(0), _1n$1 = BigInt(1); BigInt(2); const _3n = BigInt(3); BigInt(4);
 
-     function weierstrassPoints(opts) {
 
-         const CURVE = validatePointOpts(opts);
 
-         const { Fp } = CURVE; // All curves has same field / group length as for now, but they can differ
 
-         const toBytes = CURVE.toBytes ||
 
-             ((_c, point, _isCompressed) => {
 
-                 const a = point.toAffine();
 
-                 return concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y));
 
-             });
 
-         const fromBytes = CURVE.fromBytes ||
 
-             ((bytes) => {
 
-                 // const head = bytes[0];
 
-                 const tail = bytes.subarray(1);
 
-                 // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported');
 
-                 const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
 
-                 const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
 
-                 return { x, y };
 
-             });
 
-         /**
 
-          * y² = x³ + ax + b: Short weierstrass curve formula
 
-          * @returns y²
 
-          */
 
-         function weierstrassEquation(x) {
 
-             const { a, b } = CURVE;
 
-             const x2 = Fp.sqr(x); // x * x
 
-             const x3 = Fp.mul(x2, x); // x2 * x
 
-             return Fp.add(Fp.add(x3, Fp.mul(x, a)), b); // x3 + a * x + b
 
-         }
 
-         // Validate whether the passed curve params are valid.
 
-         // We check if curve equation works for generator point.
 
-         // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381.
 
-         // ProjectivePoint class has not been initialized yet.
 
-         if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
 
-             throw new Error('bad generator point: equation left != right');
 
-         // Valid group elements reside in range 1..n-1
 
-         function isWithinCurveOrder(num) {
 
-             return typeof num === 'bigint' && _0n < num && num < CURVE.n;
 
-         }
 
-         function assertGE(num) {
 
-             if (!isWithinCurveOrder(num))
 
-                 throw new Error('Expected valid bigint: 0 < bigint < curve.n');
 
-         }
 
-         // Validates if priv key is valid and converts it to bigint.
 
-         // Supports options allowedPrivateKeyLengths and wrapPrivateKey.
 
-         function normPrivateKeyToScalar(key) {
 
-             const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n } = CURVE;
 
-             if (lengths && typeof key !== 'bigint') {
 
-                 if (key instanceof Uint8Array)
 
-                     key = bytesToHex(key);
 
-                 // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
 
-                 if (typeof key !== 'string' || !lengths.includes(key.length))
 
-                     throw new Error('Invalid key');
 
-                 key = key.padStart(nByteLength * 2, '0');
 
-             }
 
-             let num;
 
-             try {
 
-                 num =
 
-                     typeof key === 'bigint'
 
-                         ? key
 
-                         : bytesToNumberBE(ensureBytes('private key', key, nByteLength));
 
-             }
 
-             catch (error) {
 
-                 throw new Error(`private key must be ${nByteLength} bytes, hex or bigint, not ${typeof key}`);
 
-             }
 
-             if (wrapPrivateKey)
 
-                 num = mod(num, n); // disabled by default, enabled for BLS
 
-             assertGE(num); // num in range [1..N-1]
 
-             return num;
 
-         }
 
-         const pointPrecomputes = new Map();
 
-         function assertPrjPoint(other) {
 
-             if (!(other instanceof Point))
 
-                 throw new Error('ProjectivePoint expected');
 
-         }
 
-         /**
 
-          * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z)
 
-          * Default Point works in 2d / affine coordinates: (x, y)
 
-          * We're doing calculations in projective, because its operations don't require costly inversion.
 
-          */
 
-         class Point {
 
-             constructor(px, py, pz) {
 
-                 this.px = px;
 
-                 this.py = py;
 
-                 this.pz = pz;
 
-                 if (px == null || !Fp.isValid(px))
 
-                     throw new Error('x required');
 
-                 if (py == null || !Fp.isValid(py))
 
-                     throw new Error('y required');
 
-                 if (pz == null || !Fp.isValid(pz))
 
-                     throw new Error('z required');
 
-             }
 
-             // Does not validate if the point is on-curve.
 
-             // Use fromHex instead, or call assertValidity() later.
 
-             static fromAffine(p) {
 
-                 const { x, y } = p || {};
 
-                 if (!p || !Fp.isValid(x) || !Fp.isValid(y))
 
-                     throw new Error('invalid affine point');
 
-                 if (p instanceof Point)
 
-                     throw new Error('projective point not allowed');
 
-                 const is0 = (i) => Fp.eql(i, Fp.ZERO);
 
-                 // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0)
 
-                 if (is0(x) && is0(y))
 
-                     return Point.ZERO;
 
-                 return new Point(x, y, Fp.ONE);
 
-             }
 
-             get x() {
 
-                 return this.toAffine().x;
 
-             }
 
-             get y() {
 
-                 return this.toAffine().y;
 
-             }
 
-             /**
 
-              * Takes a bunch of Projective Points but executes only one
 
-              * inversion on all of them. Inversion is very slow operation,
 
-              * so this improves performance massively.
 
-              * Optimization: converts a list of projective points to a list of identical points with Z=1.
 
-              */
 
-             static normalizeZ(points) {
 
-                 const toInv = Fp.invertBatch(points.map((p) => p.pz));
 
-                 return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
 
-             }
 
-             /**
 
-              * Converts hash string or Uint8Array to Point.
 
-              * @param hex short/long ECDSA hex
 
-              */
 
-             static fromHex(hex) {
 
-                 const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex)));
 
-                 P.assertValidity();
 
-                 return P;
 
-             }
 
-             // Multiplies generator point by privateKey.
 
-             static fromPrivateKey(privateKey) {
 
-                 return Point.BASE.multiply(normPrivateKeyToScalar(privateKey));
 
-             }
 
-             // "Private method", don't use it directly
 
-             _setWindowSize(windowSize) {
 
-                 this._WINDOW_SIZE = windowSize;
 
-                 pointPrecomputes.delete(this);
 
-             }
 
-             // A point on curve is valid if it conforms to equation.
 
-             assertValidity() {
 
-                 if (this.is0()) {
 
-                     // (0, 1, 0) aka ZERO is invalid in most contexts.
 
-                     // In BLS, ZERO can be serialized, so we allow it.
 
-                     // (0, 0, 0) is wrong representation of ZERO and is always invalid.
 
-                     if (CURVE.allowInfinityPoint && !Fp.is0(this.py))
 
-                         return;
 
-                     throw new Error('bad point: ZERO');
 
-                 }
 
-                 // Some 3rd-party test vectors require different wording between here & `fromCompressedHex`
 
-                 const { x, y } = this.toAffine();
 
-                 // Check if x, y are valid field elements
 
-                 if (!Fp.isValid(x) || !Fp.isValid(y))
 
-                     throw new Error('bad point: x or y not FE');
 
-                 const left = Fp.sqr(y); // y²
 
-                 const right = weierstrassEquation(x); // x³ + ax + b
 
-                 if (!Fp.eql(left, right))
 
-                     throw new Error('bad point: equation left != right');
 
-                 if (!this.isTorsionFree())
 
-                     throw new Error('bad point: not in prime-order subgroup');
 
-             }
 
-             hasEvenY() {
 
-                 const { y } = this.toAffine();
 
-                 if (Fp.isOdd)
 
-                     return !Fp.isOdd(y);
 
-                 throw new Error("Field doesn't support isOdd");
 
-             }
 
-             /**
 
-              * Compare one point to another.
 
-              */
 
-             equals(other) {
 
-                 assertPrjPoint(other);
 
-                 const { px: X1, py: Y1, pz: Z1 } = this;
 
-                 const { px: X2, py: Y2, pz: Z2 } = other;
 
-                 const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
 
-                 const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
 
-                 return U1 && U2;
 
-             }
 
-             /**
 
-              * Flips point to one corresponding to (x, -y) in Affine coordinates.
 
-              */
 
-             negate() {
 
-                 return new Point(this.px, Fp.neg(this.py), this.pz);
 
-             }
 
-             // Renes-Costello-Batina exception-free doubling formula.
 
-             // There is 30% faster Jacobian formula, but it is not complete.
 
-             // https://eprint.iacr.org/2015/1060, algorithm 3
 
-             // Cost: 8M + 3S + 3*a + 2*b3 + 15add.
 
-             double() {
 
-                 const { a, b } = CURVE;
 
-                 const b3 = Fp.mul(b, _3n);
 
-                 const { px: X1, py: Y1, pz: Z1 } = this;
 
-                 let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
 
-                 let t0 = Fp.mul(X1, X1); // step 1
 
-                 let t1 = Fp.mul(Y1, Y1);
 
-                 let t2 = Fp.mul(Z1, Z1);
 
-                 let t3 = Fp.mul(X1, Y1);
 
-                 t3 = Fp.add(t3, t3); // step 5
 
-                 Z3 = Fp.mul(X1, Z1);
 
-                 Z3 = Fp.add(Z3, Z3);
 
-                 X3 = Fp.mul(a, Z3);
 
-                 Y3 = Fp.mul(b3, t2);
 
-                 Y3 = Fp.add(X3, Y3); // step 10
 
-                 X3 = Fp.sub(t1, Y3);
 
-                 Y3 = Fp.add(t1, Y3);
 
-                 Y3 = Fp.mul(X3, Y3);
 
-                 X3 = Fp.mul(t3, X3);
 
-                 Z3 = Fp.mul(b3, Z3); // step 15
 
-                 t2 = Fp.mul(a, t2);
 
-                 t3 = Fp.sub(t0, t2);
 
-                 t3 = Fp.mul(a, t3);
 
-                 t3 = Fp.add(t3, Z3);
 
-                 Z3 = Fp.add(t0, t0); // step 20
 
-                 t0 = Fp.add(Z3, t0);
 
-                 t0 = Fp.add(t0, t2);
 
-                 t0 = Fp.mul(t0, t3);
 
-                 Y3 = Fp.add(Y3, t0);
 
-                 t2 = Fp.mul(Y1, Z1); // step 25
 
-                 t2 = Fp.add(t2, t2);
 
-                 t0 = Fp.mul(t2, t3);
 
-                 X3 = Fp.sub(X3, t0);
 
-                 Z3 = Fp.mul(t2, t1);
 
-                 Z3 = Fp.add(Z3, Z3); // step 30
 
-                 Z3 = Fp.add(Z3, Z3);
 
-                 return new Point(X3, Y3, Z3);
 
-             }
 
-             // Renes-Costello-Batina exception-free addition formula.
 
-             // There is 30% faster Jacobian formula, but it is not complete.
 
-             // https://eprint.iacr.org/2015/1060, algorithm 1
 
-             // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
 
-             add(other) {
 
-                 assertPrjPoint(other);
 
-                 const { px: X1, py: Y1, pz: Z1 } = this;
 
-                 const { px: X2, py: Y2, pz: Z2 } = other;
 
-                 let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO; // prettier-ignore
 
-                 const a = CURVE.a;
 
-                 const b3 = Fp.mul(CURVE.b, _3n);
 
-                 let t0 = Fp.mul(X1, X2); // step 1
 
-                 let t1 = Fp.mul(Y1, Y2);
 
-                 let t2 = Fp.mul(Z1, Z2);
 
-                 let t3 = Fp.add(X1, Y1);
 
-                 let t4 = Fp.add(X2, Y2); // step 5
 
-                 t3 = Fp.mul(t3, t4);
 
-                 t4 = Fp.add(t0, t1);
 
-                 t3 = Fp.sub(t3, t4);
 
-                 t4 = Fp.add(X1, Z1);
 
-                 let t5 = Fp.add(X2, Z2); // step 10
 
-                 t4 = Fp.mul(t4, t5);
 
-                 t5 = Fp.add(t0, t2);
 
-                 t4 = Fp.sub(t4, t5);
 
-                 t5 = Fp.add(Y1, Z1);
 
-                 X3 = Fp.add(Y2, Z2); // step 15
 
-                 t5 = Fp.mul(t5, X3);
 
-                 X3 = Fp.add(t1, t2);
 
-                 t5 = Fp.sub(t5, X3);
 
-                 Z3 = Fp.mul(a, t4);
 
-                 X3 = Fp.mul(b3, t2); // step 20
 
-                 Z3 = Fp.add(X3, Z3);
 
-                 X3 = Fp.sub(t1, Z3);
 
-                 Z3 = Fp.add(t1, Z3);
 
-                 Y3 = Fp.mul(X3, Z3);
 
-                 t1 = Fp.add(t0, t0); // step 25
 
-                 t1 = Fp.add(t1, t0);
 
-                 t2 = Fp.mul(a, t2);
 
-                 t4 = Fp.mul(b3, t4);
 
-                 t1 = Fp.add(t1, t2);
 
-                 t2 = Fp.sub(t0, t2); // step 30
 
-                 t2 = Fp.mul(a, t2);
 
-                 t4 = Fp.add(t4, t2);
 
-                 t0 = Fp.mul(t1, t4);
 
-                 Y3 = Fp.add(Y3, t0);
 
-                 t0 = Fp.mul(t5, t4); // step 35
 
-                 X3 = Fp.mul(t3, X3);
 
-                 X3 = Fp.sub(X3, t0);
 
-                 t0 = Fp.mul(t3, t1);
 
-                 Z3 = Fp.mul(t5, Z3);
 
-                 Z3 = Fp.add(Z3, t0); // step 40
 
-                 return new Point(X3, Y3, Z3);
 
-             }
 
-             subtract(other) {
 
-                 return this.add(other.negate());
 
-             }
 
-             is0() {
 
-                 return this.equals(Point.ZERO);
 
-             }
 
-             wNAF(n) {
 
-                 return wnaf.wNAFCached(this, pointPrecomputes, n, (comp) => {
 
-                     const toInv = Fp.invertBatch(comp.map((p) => p.pz));
 
-                     return comp.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine);
 
-                 });
 
-             }
 
-             /**
 
-              * Non-constant-time multiplication. Uses double-and-add algorithm.
 
-              * It's faster, but should only be used when you don't care about
 
-              * an exposed private key e.g. sig verification, which works over *public* keys.
 
-              */
 
-             multiplyUnsafe(n) {
 
-                 const I = Point.ZERO;
 
-                 if (n === _0n)
 
-                     return I;
 
-                 assertGE(n); // Will throw on 0
 
-                 if (n === _1n$1)
 
-                     return this;
 
-                 const { endo } = CURVE;
 
-                 if (!endo)
 
-                     return wnaf.unsafeLadder(this, n);
 
-                 // Apply endomorphism
 
-                 let { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
 
-                 let k1p = I;
 
-                 let k2p = I;
 
-                 let d = this;
 
-                 while (k1 > _0n || k2 > _0n) {
 
-                     if (k1 & _1n$1)
 
-                         k1p = k1p.add(d);
 
-                     if (k2 & _1n$1)
 
-                         k2p = k2p.add(d);
 
-                     d = d.double();
 
-                     k1 >>= _1n$1;
 
-                     k2 >>= _1n$1;
 
-                 }
 
-                 if (k1neg)
 
-                     k1p = k1p.negate();
 
-                 if (k2neg)
 
-                     k2p = k2p.negate();
 
-                 k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
 
-                 return k1p.add(k2p);
 
-             }
 
-             /**
 
-              * Constant time multiplication.
 
-              * Uses wNAF method. Windowed method may be 10% faster,
 
-              * but takes 2x longer to generate and consumes 2x memory.
 
-              * Uses precomputes when available.
 
-              * Uses endomorphism for Koblitz curves.
 
-              * @param scalar by which the point would be multiplied
 
-              * @returns New point
 
-              */
 
-             multiply(scalar) {
 
-                 assertGE(scalar);
 
-                 let n = scalar;
 
-                 let point, fake; // Fake point is used to const-time mult
 
-                 const { endo } = CURVE;
 
-                 if (endo) {
 
-                     const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
 
-                     let { p: k1p, f: f1p } = this.wNAF(k1);
 
-                     let { p: k2p, f: f2p } = this.wNAF(k2);
 
-                     k1p = wnaf.constTimeNegate(k1neg, k1p);
 
-                     k2p = wnaf.constTimeNegate(k2neg, k2p);
 
-                     k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
 
-                     point = k1p.add(k2p);
 
-                     fake = f1p.add(f2p);
 
-                 }
 
-                 else {
 
-                     const { p, f } = this.wNAF(n);
 
-                     point = p;
 
-                     fake = f;
 
-                 }
 
-                 // Normalize `z` for both points, but return only real one
 
-                 return Point.normalizeZ([point, fake])[0];
 
-             }
 
-             /**
 
-              * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
 
-              * Not using Strauss-Shamir trick: precomputation tables are faster.
 
-              * The trick could be useful if both P and Q are not G (not in our case).
 
-              * @returns non-zero affine point
 
-              */
 
-             multiplyAndAddUnsafe(Q, a, b) {
 
-                 const G = Point.BASE; // No Strauss-Shamir trick: we have 10% faster G precomputes
 
-                 const mul = (P, a // Select faster multiply() method
 
-                 ) => (a === _0n || a === _1n$1 || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a));
 
-                 const sum = mul(this, a).add(mul(Q, b));
 
-                 return sum.is0() ? undefined : sum;
 
-             }
 
-             // Converts Projective point to affine (x, y) coordinates.
 
-             // Can accept precomputed Z^-1 - for example, from invertBatch.
 
-             // (x, y, z) ∋ (x=x/z, y=y/z)
 
-             toAffine(iz) {
 
-                 const { px: x, py: y, pz: z } = this;
 
-                 const is0 = this.is0();
 
-                 // If invZ was 0, we return zero point. However we still want to execute
 
-                 // all operations, so we replace invZ with a random number, 1.
 
-                 if (iz == null)
 
-                     iz = is0 ? Fp.ONE : Fp.inv(z);
 
-                 const ax = Fp.mul(x, iz);
 
-                 const ay = Fp.mul(y, iz);
 
-                 const zz = Fp.mul(z, iz);
 
-                 if (is0)
 
-                     return { x: Fp.ZERO, y: Fp.ZERO };
 
-                 if (!Fp.eql(zz, Fp.ONE))
 
-                     throw new Error('invZ was invalid');
 
-                 return { x: ax, y: ay };
 
-             }
 
-             isTorsionFree() {
 
-                 const { h: cofactor, isTorsionFree } = CURVE;
 
-                 if (cofactor === _1n$1)
 
-                     return true; // No subgroups, always torsion-free
 
-                 if (isTorsionFree)
 
-                     return isTorsionFree(Point, this);
 
-                 throw new Error('isTorsionFree() has not been declared for the elliptic curve');
 
-             }
 
-             clearCofactor() {
 
-                 const { h: cofactor, clearCofactor } = CURVE;
 
-                 if (cofactor === _1n$1)
 
-                     return this; // Fast-path
 
-                 if (clearCofactor)
 
-                     return clearCofactor(Point, this);
 
-                 return this.multiplyUnsafe(CURVE.h);
 
-             }
 
-             toRawBytes(isCompressed = true) {
 
-                 this.assertValidity();
 
-                 return toBytes(Point, this, isCompressed);
 
-             }
 
-             toHex(isCompressed = true) {
 
-                 return bytesToHex(this.toRawBytes(isCompressed));
 
-             }
 
-         }
 
-         Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
 
-         Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO);
 
-         const _bits = CURVE.nBitLength;
 
-         const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
 
-         // Validate if generator point is on curve
 
-         return {
 
-             CURVE,
 
-             ProjectivePoint: Point,
 
-             normPrivateKeyToScalar,
 
-             weierstrassEquation,
 
-             isWithinCurveOrder,
 
-         };
 
-     }
 
-     function validateOpts(curve) {
 
-         const opts = validateBasic(curve);
 
-         validateObject(opts, {
 
-             hash: 'hash',
 
-             hmac: 'function',
 
-             randomBytes: 'function',
 
-         }, {
 
-             bits2int: 'function',
 
-             bits2int_modN: 'function',
 
-             lowS: 'boolean',
 
-         });
 
-         return Object.freeze({ lowS: true, ...opts });
 
-     }
 
-     function weierstrass(curveDef) {
 
-         const CURVE = validateOpts(curveDef);
 
-         const { Fp, n: CURVE_ORDER } = CURVE;
 
-         const compressedLen = Fp.BYTES + 1; // e.g. 33 for 32
 
-         const uncompressedLen = 2 * Fp.BYTES + 1; // e.g. 65 for 32
 
-         function isValidFieldElement(num) {
 
-             return _0n < num && num < Fp.ORDER; // 0 is banned since it's not invertible FE
 
-         }
 
-         function modN(a) {
 
-             return mod(a, CURVE_ORDER);
 
-         }
 
-         function invN(a) {
 
-             return invert(a, CURVE_ORDER);
 
-         }
 
-         const { ProjectivePoint: Point, normPrivateKeyToScalar, weierstrassEquation, isWithinCurveOrder, } = weierstrassPoints({
 
-             ...CURVE,
 
-             toBytes(_c, point, isCompressed) {
 
-                 const a = point.toAffine();
 
-                 const x = Fp.toBytes(a.x);
 
-                 const cat = concatBytes;
 
-                 if (isCompressed) {
 
-                     return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x);
 
-                 }
 
-                 else {
 
-                     return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y));
 
-                 }
 
-             },
 
-             fromBytes(bytes) {
 
-                 const len = bytes.length;
 
-                 const head = bytes[0];
 
-                 const tail = bytes.subarray(1);
 
-                 // this.assertValidity() is done inside of fromHex
 
-                 if (len === compressedLen && (head === 0x02 || head === 0x03)) {
 
-                     const x = bytesToNumberBE(tail);
 
-                     if (!isValidFieldElement(x))
 
-                         throw new Error('Point is not on curve');
 
-                     const y2 = weierstrassEquation(x); // y² = x³ + ax + b
 
-                     let y = Fp.sqrt(y2); // y = y² ^ (p+1)/4
 
-                     const isYOdd = (y & _1n$1) === _1n$1;
 
-                     // ECDSA
 
-                     const isHeadOdd = (head & 1) === 1;
 
-                     if (isHeadOdd !== isYOdd)
 
-                         y = Fp.neg(y);
 
-                     return { x, y };
 
-                 }
 
-                 else if (len === uncompressedLen && head === 0x04) {
 
-                     const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
 
-                     const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
 
-                     return { x, y };
 
-                 }
 
-                 else {
 
-                     throw new Error(`Point of length ${len} was invalid. Expected ${compressedLen} compressed bytes or ${uncompressedLen} uncompressed bytes`);
 
-                 }
 
-             },
 
-         });
 
-         const numToNByteStr = (num) => bytesToHex(numberToBytesBE(num, CURVE.nByteLength));
 
-         function isBiggerThanHalfOrder(number) {
 
-             const HALF = CURVE_ORDER >> _1n$1;
 
-             return number > HALF;
 
-         }
 
-         function normalizeS(s) {
 
-             return isBiggerThanHalfOrder(s) ? modN(-s) : s;
 
-         }
 
-         // slice bytes num
 
-         const slcNum = (b, from, to) => bytesToNumberBE(b.slice(from, to));
 
-         /**
 
-          * ECDSA signature with its (r, s) properties. Supports DER & compact representations.
 
-          */
 
-         class Signature {
 
-             constructor(r, s, recovery) {
 
-                 this.r = r;
 
-                 this.s = s;
 
-                 this.recovery = recovery;
 
-                 this.assertValidity();
 
-             }
 
-             // pair (bytes of r, bytes of s)
 
-             static fromCompact(hex) {
 
-                 const l = CURVE.nByteLength;
 
-                 hex = ensureBytes('compactSignature', hex, l * 2);
 
-                 return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l));
 
-             }
 
-             // DER encoded ECDSA signature
 
-             // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script
 
-             static fromDER(hex) {
 
-                 const { r, s } = DER.toSig(ensureBytes('DER', hex));
 
-                 return new Signature(r, s);
 
-             }
 
-             assertValidity() {
 
-                 // can use assertGE here
 
-                 if (!isWithinCurveOrder(this.r))
 
-                     throw new Error('r must be 0 < r < CURVE.n');
 
-                 if (!isWithinCurveOrder(this.s))
 
-                     throw new Error('s must be 0 < s < CURVE.n');
 
-             }
 
-             addRecoveryBit(recovery) {
 
-                 return new Signature(this.r, this.s, recovery);
 
-             }
 
-             recoverPublicKey(msgHash) {
 
-                 const { r, s, recovery: rec } = this;
 
-                 const h = bits2int_modN(ensureBytes('msgHash', msgHash)); // Truncate hash
 
-                 if (rec == null || ![0, 1, 2, 3].includes(rec))
 
-                     throw new Error('recovery id invalid');
 
-                 const radj = rec === 2 || rec === 3 ? r + CURVE.n : r;
 
-                 if (radj >= Fp.ORDER)
 
-                     throw new Error('recovery id 2 or 3 invalid');
 
-                 const prefix = (rec & 1) === 0 ? '02' : '03';
 
-                 const R = Point.fromHex(prefix + numToNByteStr(radj));
 
-                 const ir = invN(radj); // r^-1
 
-                 const u1 = modN(-h * ir); // -hr^-1
 
-                 const u2 = modN(s * ir); // sr^-1
 
-                 const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2); // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1)
 
-                 if (!Q)
 
-                     throw new Error('point at infinify'); // unsafe is fine: no priv data leaked
 
-                 Q.assertValidity();
 
-                 return Q;
 
-             }
 
-             // Signatures should be low-s, to prevent malleability.
 
-             hasHighS() {
 
-                 return isBiggerThanHalfOrder(this.s);
 
-             }
 
-             normalizeS() {
 
-                 return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this;
 
-             }
 
-             // DER-encoded
 
-             toDERRawBytes() {
 
-                 return hexToBytes(this.toDERHex());
 
-             }
 
-             toDERHex() {
 
-                 return DER.hexFromSig({ r: this.r, s: this.s });
 
-             }
 
-             // padded bytes of r, then padded bytes of s
 
-             toCompactRawBytes() {
 
-                 return hexToBytes(this.toCompactHex());
 
-             }
 
-             toCompactHex() {
 
-                 return numToNByteStr(this.r) + numToNByteStr(this.s);
 
-             }
 
-         }
 
-         const utils = {
 
-             isValidPrivateKey(privateKey) {
 
-                 try {
 
-                     normPrivateKeyToScalar(privateKey);
 
-                     return true;
 
-                 }
 
-                 catch (error) {
 
-                     return false;
 
-                 }
 
-             },
 
-             normPrivateKeyToScalar: normPrivateKeyToScalar,
 
-             /**
 
-              * Produces cryptographically secure private key from random of size
 
-              * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
 
-              */
 
-             randomPrivateKey: () => {
 
-                 const length = getMinHashLength(CURVE.n);
 
-                 return mapHashToField(CURVE.randomBytes(length), CURVE.n);
 
-             },
 
-             /**
 
-              * Creates precompute table for an arbitrary EC point. Makes point "cached".
 
-              * Allows to massively speed-up `point.multiply(scalar)`.
 
-              * @returns cached point
 
-              * @example
 
-              * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey));
 
-              * fast.multiply(privKey); // much faster ECDH now
 
-              */
 
-             precompute(windowSize = 8, point = Point.BASE) {
 
-                 point._setWindowSize(windowSize);
 
-                 point.multiply(BigInt(3)); // 3 is arbitrary, just need any number here
 
-                 return point;
 
-             },
 
-         };
 
-         /**
 
-          * Computes public key for a private key. Checks for validity of the private key.
 
-          * @param privateKey private key
 
-          * @param isCompressed whether to return compact (default), or full key
 
-          * @returns Public key, full when isCompressed=false; short when isCompressed=true
 
-          */
 
-         function getPublicKey(privateKey, isCompressed = true) {
 
-             return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed);
 
-         }
 
-         /**
 
-          * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
 
-          */
 
-         function isProbPub(item) {
 
-             const arr = item instanceof Uint8Array;
 
-             const str = typeof item === 'string';
 
-             const len = (arr || str) && item.length;
 
-             if (arr)
 
-                 return len === compressedLen || len === uncompressedLen;
 
-             if (str)
 
-                 return len === 2 * compressedLen || len === 2 * uncompressedLen;
 
-             if (item instanceof Point)
 
-                 return true;
 
-             return false;
 
-         }
 
-         /**
 
-          * ECDH (Elliptic Curve Diffie Hellman).
 
-          * Computes shared public key from private key and public key.
 
-          * Checks: 1) private key validity 2) shared key is on-curve.
 
-          * Does NOT hash the result.
 
-          * @param privateA private key
 
-          * @param publicB different public key
 
-          * @param isCompressed whether to return compact (default), or full key
 
-          * @returns shared public key
 
-          */
 
-         function getSharedSecret(privateA, publicB, isCompressed = true) {
 
-             if (isProbPub(privateA))
 
-                 throw new Error('first arg must be private key');
 
-             if (!isProbPub(publicB))
 
-                 throw new Error('second arg must be public key');
 
-             const b = Point.fromHex(publicB); // check for being on-curve
 
-             return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed);
 
-         }
 
-         // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
 
-         // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
 
-         // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same.
 
-         // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
 
-         const bits2int = CURVE.bits2int ||
 
-             function (bytes) {
 
-                 // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
 
-                 // for some cases, since bytes.length * 8 is not actual bitLength.
 
-                 const num = bytesToNumberBE(bytes); // check for == u8 done here
 
-                 const delta = bytes.length * 8 - CURVE.nBitLength; // truncate to nBitLength leftmost bits
 
-                 return delta > 0 ? num >> BigInt(delta) : num;
 
-             };
 
-         const bits2int_modN = CURVE.bits2int_modN ||
 
-             function (bytes) {
 
-                 return modN(bits2int(bytes)); // can't use bytesToNumberBE here
 
-             };
 
-         // NOTE: pads output with zero as per spec
 
-         const ORDER_MASK = bitMask(CURVE.nBitLength);
 
-         /**
 
-          * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
 
-          */
 
-         function int2octets(num) {
 
-             if (typeof num !== 'bigint')
 
-                 throw new Error('bigint expected');
 
-             if (!(_0n <= num && num < ORDER_MASK))
 
-                 throw new Error(`bigint expected < 2^${CURVE.nBitLength}`);
 
-             // works with order, can have different size than numToField!
 
-             return numberToBytesBE(num, CURVE.nByteLength);
 
-         }
 
-         // Steps A, D of RFC6979 3.2
 
-         // Creates RFC6979 seed; converts msg/privKey to numbers.
 
-         // Used only in sign, not in verify.
 
-         // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, this will be wrong at least for P521.
 
-         // Also it can be bigger for P224 + SHA256
 
-         function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
 
-             if (['recovered', 'canonical'].some((k) => k in opts))
 
-                 throw new Error('sign() legacy options not supported');
 
-             const { hash, randomBytes } = CURVE;
 
-             let { lowS, prehash, extraEntropy: ent } = opts; // generates low-s sigs by default
 
-             if (lowS == null)
 
-                 lowS = true; // RFC6979 3.2: we skip step A, because we already provide hash
 
-             msgHash = ensureBytes('msgHash', msgHash);
 
-             if (prehash)
 
-                 msgHash = ensureBytes('prehashed msgHash', hash(msgHash));
 
-             // We can't later call bits2octets, since nested bits2int is broken for curves
 
-             // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call.
 
-             // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
 
-             const h1int = bits2int_modN(msgHash);
 
-             const d = normPrivateKeyToScalar(privateKey); // validate private key, convert to bigint
 
-             const seedArgs = [int2octets(d), int2octets(h1int)];
 
-             // extraEntropy. RFC6979 3.6: additional k' (optional).
 
-             if (ent != null) {
 
-                 // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
 
-                 const e = ent === true ? randomBytes(Fp.BYTES) : ent; // generate random bytes OR pass as-is
 
-                 seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
 
-             }
 
-             const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2
 
-             const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
 
-             // Converts signature params into point w r/s, checks result for validity.
 
-             function k2sig(kBytes) {
 
-                 // RFC 6979 Section 3.2, step 3: k = bits2int(T)
 
-                 const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
 
-                 if (!isWithinCurveOrder(k))
 
-                     return; // Important: all mod() calls here must be done over N
 
-                 const ik = invN(k); // k^-1 mod n
 
-                 const q = Point.BASE.multiply(k).toAffine(); // q = Gk
 
-                 const r = modN(q.x); // r = q.x mod n
 
-                 if (r === _0n)
 
-                     return;
 
-                 // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to
 
-                 // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it:
 
-                 // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT
 
-                 const s = modN(ik * modN(m + r * d)); // Not using blinding here
 
-                 if (s === _0n)
 
-                     return;
 
-                 let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$1); // recovery bit (2 or 3, when q.x > n)
 
-                 let normS = s;
 
-                 if (lowS && isBiggerThanHalfOrder(s)) {
 
-                     normS = normalizeS(s); // if lowS was passed, ensure s is always
 
-                     recovery ^= 1; // // in the bottom half of N
 
-                 }
 
-                 return new Signature(r, normS, recovery); // use normS, not s
 
-             }
 
-             return { seed, k2sig };
 
-         }
 
-         const defaultSigOpts = { lowS: CURVE.lowS, prehash: false };
 
-         const defaultVerOpts = { lowS: CURVE.lowS, prehash: false };
 
-         /**
 
-          * Signs message hash with a private key.
 
-          * ```
 
-          * sign(m, d, k) where
 
-          *   (x, y) = G × k
 
-          *   r = x mod n
 
-          *   s = (m + dr)/k mod n
 
-          * ```
 
-          * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`.
 
-          * @param privKey private key
 
-          * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg.
 
-          * @returns signature with recovery param
 
-          */
 
-         function sign(msgHash, privKey, opts = defaultSigOpts) {
 
-             const { seed, k2sig } = prepSig(msgHash, privKey, opts); // Steps A, D of RFC6979 3.2.
 
-             const C = CURVE;
 
-             const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac);
 
-             return drbg(seed, k2sig); // Steps B, C, D, E, F, G
 
-         }
 
-         // Enable precomputes. Slows down first publicKey computation by 20ms.
 
-         Point.BASE._setWindowSize(8);
 
-         // utils.precompute(8, ProjectivePoint.BASE)
 
-         /**
 
-          * Verifies a signature against message hash and public key.
 
-          * Rejects lowS signatures by default: to override,
 
-          * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf:
 
-          *
 
-          * ```
 
-          * verify(r, s, h, P) where
 
-          *   U1 = hs^-1 mod n
 
-          *   U2 = rs^-1 mod n
 
-          *   R = U1⋅G - U2⋅P
 
-          *   mod(R.x, n) == r
 
-          * ```
 
-          */
 
-         function verify(signature, msgHash, publicKey, opts = defaultVerOpts) {
 
-             const sg = signature;
 
-             msgHash = ensureBytes('msgHash', msgHash);
 
-             publicKey = ensureBytes('publicKey', publicKey);
 
-             if ('strict' in opts)
 
-                 throw new Error('options.strict was renamed to lowS');
 
-             const { lowS, prehash } = opts;
 
-             let _sig = undefined;
 
-             let P;
 
-             try {
 
-                 if (typeof sg === 'string' || sg instanceof Uint8Array) {
 
-                     // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
 
-                     // Since DER can also be 2*nByteLength bytes, we check for it first.
 
-                     try {
 
-                         _sig = Signature.fromDER(sg);
 
-                     }
 
-                     catch (derError) {
 
-                         if (!(derError instanceof DER.Err))
 
-                             throw derError;
 
-                         _sig = Signature.fromCompact(sg);
 
-                     }
 
-                 }
 
-                 else if (typeof sg === 'object' && typeof sg.r === 'bigint' && typeof sg.s === 'bigint') {
 
-                     const { r, s } = sg;
 
-                     _sig = new Signature(r, s);
 
-                 }
 
-                 else {
 
-                     throw new Error('PARSE');
 
-                 }
 
-                 P = Point.fromHex(publicKey);
 
-             }
 
-             catch (error) {
 
-                 if (error.message === 'PARSE')
 
-                     throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
 
-                 return false;
 
-             }
 
-             if (lowS && _sig.hasHighS())
 
-                 return false;
 
-             if (prehash)
 
-                 msgHash = CURVE.hash(msgHash);
 
-             const { r, s } = _sig;
 
-             const h = bits2int_modN(msgHash); // Cannot use fields methods, since it is group element
 
-             const is = invN(s); // s^-1
 
-             const u1 = modN(h * is); // u1 = hs^-1 mod n
 
-             const u2 = modN(r * is); // u2 = rs^-1 mod n
 
-             const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine(); // R = u1⋅G + u2⋅P
 
-             if (!R)
 
-                 return false;
 
-             const v = modN(R.x);
 
-             return v === r;
 
-         }
 
-         return {
 
-             CURVE,
 
-             getPublicKey,
 
-             getSharedSecret,
 
-             sign,
 
-             verify,
 
-             ProjectivePoint: Point,
 
-             Signature,
 
-             utils,
 
-         };
 
-     }
 
-     /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
 
-     // connects noble-curves to noble-hashes
 
-     function getHash(hash) {
 
-         return {
 
-             hash,
 
-             hmac: (key, ...msgs) => hmac(hash, key, concatBytes$1(...msgs)),
 
-             randomBytes: randomBytes$2,
 
-         };
 
-     }
 
-     function createCurve(curveDef, defHash) {
 
-         const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) });
 
-         return Object.freeze({ ...create(defHash), create });
 
-     }
 
-     /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
 
-     const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
 
-     const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
 
-     const _1n = BigInt(1);
 
-     const _2n = BigInt(2);
 
-     const divNearest = (a, b) => (a + b / _2n) / b;
 
-     /**
 
-      * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.
 
-      * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00]
 
-      */
 
-     function sqrtMod(y) {
 
-         const P = secp256k1P;
 
-         // prettier-ignore
 
-         const _3n = BigInt(3), _6n = BigInt(6), _11n = BigInt(11), _22n = BigInt(22);
 
-         // prettier-ignore
 
-         const _23n = BigInt(23), _44n = BigInt(44), _88n = BigInt(88);
 
-         const b2 = (y * y * y) % P; // x^3, 11
 
-         const b3 = (b2 * b2 * y) % P; // x^7
 
-         const b6 = (pow2(b3, _3n, P) * b3) % P;
 
-         const b9 = (pow2(b6, _3n, P) * b3) % P;
 
-         const b11 = (pow2(b9, _2n, P) * b2) % P;
 
-         const b22 = (pow2(b11, _11n, P) * b11) % P;
 
-         const b44 = (pow2(b22, _22n, P) * b22) % P;
 
-         const b88 = (pow2(b44, _44n, P) * b44) % P;
 
-         const b176 = (pow2(b88, _88n, P) * b88) % P;
 
-         const b220 = (pow2(b176, _44n, P) * b44) % P;
 
-         const b223 = (pow2(b220, _3n, P) * b3) % P;
 
-         const t1 = (pow2(b223, _23n, P) * b22) % P;
 
-         const t2 = (pow2(t1, _6n, P) * b2) % P;
 
-         const root = pow2(t2, _2n, P);
 
-         if (!Fp.eql(Fp.sqr(root), y))
 
-             throw new Error('Cannot find square root');
 
-         return root;
 
-     }
 
-     const Fp = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
 
-     const secp256k1 = createCurve({
 
-         a: BigInt(0),
 
-         b: BigInt(7),
 
-         Fp,
 
-         n: secp256k1N,
 
-         // Base point (x, y) aka generator point
 
-         Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
 
-         Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
 
-         h: BigInt(1),
 
-         lowS: true,
 
-         /**
 
-          * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
 
-          * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
 
-          * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
 
-          * Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
 
-          */
 
-         endo: {
 
-             beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
 
-             splitScalar: (k) => {
 
-                 const n = secp256k1N;
 
-                 const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15');
 
-                 const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3');
 
-                 const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8');
 
-                 const b2 = a1;
 
-                 const POW_2_128 = BigInt('0x100000000000000000000000000000000'); // (2n**128n).toString(16)
 
-                 const c1 = divNearest(b2 * k, n);
 
-                 const c2 = divNearest(-b1 * k, n);
 
-                 let k1 = mod(k - c1 * a1 - c2 * a2, n);
 
-                 let k2 = mod(-c1 * b1 - c2 * b2, n);
 
-                 const k1neg = k1 > POW_2_128;
 
-                 const k2neg = k2 > POW_2_128;
 
-                 if (k1neg)
 
-                     k1 = n - k1;
 
-                 if (k2neg)
 
-                     k2 = n - k2;
 
-                 if (k1 > POW_2_128 || k2 > POW_2_128) {
 
-                     throw new Error('splitScalar: Endomorphism failed, k=' + k);
 
-                 }
 
-                 return { k1neg, k1, k2neg, k2 };
 
-             },
 
-         },
 
-     }, sha256$1);
 
-     // Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
 
-     // https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
 
-     BigInt(0);
 
-     secp256k1.ProjectivePoint;
 
-     /**
 
-      *  A constant for the zero address.
 
-      *
 
-      *  (**i.e.** ``"0x0000000000000000000000000000000000000000"``)
 
-      */
 
-     const ZeroAddress = "0x0000000000000000000000000000000000000000";
 
-     /**
 
-      *  A constant for the zero hash.
 
-      *
 
-      *  (**i.e.** ``"0x0000000000000000000000000000000000000000000000000000000000000000"``)
 
-      */
 
-     const ZeroHash = "0x0000000000000000000000000000000000000000000000000000000000000000";
 
-     /**
 
-      *  A constant for the order N for the secp256k1 curve.
 
-      *
 
-      *  (**i.e.** ``0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n``)
 
-      */
 
-     const N$1 = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
 
-     /**
 
-      *  A constant for the number of wei in a single ether.
 
-      *
 
-      *  (**i.e.** ``1000000000000000000n``)
 
-      */
 
-     const WeiPerEther = BigInt("1000000000000000000");
 
-     /**
 
-      *  A constant for the maximum value for a ``uint256``.
 
-      *
 
-      *  (**i.e.** ``0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn``)
 
-      */
 
-     const MaxUint256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
 
-     /**
 
-      *  A constant for the minimum value for an ``int256``.
 
-      *
 
-      *  (**i.e.** ``-8000000000000000000000000000000000000000000000000000000000000000n``)
 
-      */
 
-     const MinInt256 = BigInt("0x8000000000000000000000000000000000000000000000000000000000000000") * BigInt(-1);
 
-     /**
 
-      *  A constant for the maximum value for an ``int256``.
 
-      *
 
-      *  (**i.e.** ``0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn``)
 
-      */
 
-     const MaxInt256 = BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
 
-     // NFKC (composed)             // (decomposed)
 
-     /**
 
-      *  A constant for the ether symbol (normalized using NFKC).
 
-      *
 
-      *  (**i.e.** ``"\\u039e"``)
 
-      */
 
-     const EtherSymbol = "\u039e"; // "\uD835\uDF63";
 
-     /**
 
-      *  A constant for the [[link-eip-191]] personal message prefix.
 
-      *
 
-      *  (**i.e.** ``"\\x19Ethereum Signed Message:\\n"``)
 
-      */
 
-     const MessagePrefix = "\x19Ethereum Signed Message:\n";
 
-     // Constants
 
-     const BN_0$7 = BigInt(0);
 
-     const BN_1$3 = BigInt(1);
 
-     const BN_2$3 = BigInt(2);
 
-     const BN_27$1 = BigInt(27);
 
-     const BN_28$1 = BigInt(28);
 
-     const BN_35$1 = BigInt(35);
 
-     const _guard$3 = {};
 
-     function toUint256(value) {
 
-         return zeroPadValue(toBeArray(value), 32);
 
-     }
 
-     /**
 
-      *  A Signature  @TODO
 
-      *
 
-      *
 
-      *  @_docloc: api/crypto:Signing
 
-      */
 
-     class Signature {
 
-         #r;
 
-         #s;
 
-         #v;
 
-         #networkV;
 
-         /**
 
-          *  The ``r`` value for a signautre.
 
-          *
 
-          *  This represents the ``x`` coordinate of a "reference" or
 
-          *  challenge point, from which the ``y`` can be computed.
 
-          */
 
-         get r() { return this.#r; }
 
-         set r(value) {
 
-             assertArgument(dataLength(value) === 32, "invalid r", "value", value);
 
-             this.#r = hexlify(value);
 
-         }
 
-         /**
 
-          *  The ``s`` value for a signature.
 
-          */
 
-         get s() { return this.#s; }
 
-         set s(_value) {
 
-             assertArgument(dataLength(_value) === 32, "invalid s", "value", _value);
 
-             const value = hexlify(_value);
 
-             assertArgument(parseInt(value.substring(0, 3)) < 8, "non-canonical s", "value", value);
 
-             this.#s = value;
 
-         }
 
-         /**
 
-          *  The ``v`` value for a signature.
 
-          *
 
-          *  Since a given ``x`` value for ``r`` has two possible values for
 
-          *  its correspondin ``y``, the ``v`` indicates which of the two ``y``
 
-          *  values to use.
 
-          *
 
-          *  It is normalized to the values ``27`` or ``28`` for legacy
 
-          *  purposes.
 
-          */
 
-         get v() { return this.#v; }
 
-         set v(value) {
 
-             const v = getNumber(value, "value");
 
-             assertArgument(v === 27 || v === 28, "invalid v", "v", value);
 
-             this.#v = v;
 
-         }
 
-         /**
 
-          *  The EIP-155 ``v`` for legacy transactions. For non-legacy
 
-          *  transactions, this value is ``null``.
 
-          */
 
-         get networkV() { return this.#networkV; }
 
-         /**
 
-          *  The chain ID for EIP-155 legacy transactions. For non-legacy
 
-          *  transactions, this value is ``null``.
 
-          */
 
-         get legacyChainId() {
 
-             const v = this.networkV;
 
-             if (v == null) {
 
-                 return null;
 
-             }
 
-             return Signature.getChainId(v);
 
-         }
 
-         /**
 
-          *  The ``yParity`` for the signature.
 
-          *
 
-          *  See ``v`` for more details on how this value is used.
 
-          */
 
-         get yParity() {
 
-             return (this.v === 27) ? 0 : 1;
 
-         }
 
-         /**
 
-          *  The [[link-eip-2098]] compact representation of the ``yParity``
 
-          *  and ``s`` compacted into a single ``bytes32``.
 
-          */
 
-         get yParityAndS() {
 
-             // The EIP-2098 compact representation
 
-             const yParityAndS = getBytes(this.s);
 
-             if (this.yParity) {
 
-                 yParityAndS[0] |= 0x80;
 
-             }
 
-             return hexlify(yParityAndS);
 
-         }
 
-         /**
 
-          *  The [[link-eip-2098]] compact representation.
 
-          */
 
-         get compactSerialized() {
 
-             return concat([this.r, this.yParityAndS]);
 
-         }
 
-         /**
 
-          *  The serialized representation.
 
-          */
 
-         get serialized() {
 
-             return concat([this.r, this.s, (this.yParity ? "0x1c" : "0x1b")]);
 
-         }
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, r, s, v) {
 
-             assertPrivate(guard, _guard$3, "Signature");
 
-             this.#r = r;
 
-             this.#s = s;
 
-             this.#v = v;
 
-             this.#networkV = null;
 
-         }
 
-         [Symbol.for('nodejs.util.inspect.custom')]() {
 
-             return `Signature { r: "${this.r}", s: "${this.s}", yParity: ${this.yParity}, networkV: ${this.networkV} }`;
 
-         }
 
-         /**
 
-          *  Returns a new identical [[Signature]].
 
-          */
 
-         clone() {
 
-             const clone = new Signature(_guard$3, this.r, this.s, this.v);
 
-             if (this.networkV) {
 
-                 clone.#networkV = this.networkV;
 
-             }
 
-             return clone;
 
-         }
 
-         /**
 
-          *  Returns a representation that is compatible with ``JSON.stringify``.
 
-          */
 
-         toJSON() {
 
-             const networkV = this.networkV;
 
-             return {
 
-                 _type: "signature",
 
-                 networkV: ((networkV != null) ? networkV.toString() : null),
 
-                 r: this.r, s: this.s, v: this.v,
 
-             };
 
-         }
 
-         /**
 
-          *  Compute the chain ID from the ``v`` in a legacy EIP-155 transactions.
 
-          *
 
-          *  @example:
 
-          *    Signature.getChainId(45)
 
-          *    //_result:
 
-          *
 
-          *    Signature.getChainId(46)
 
-          *    //_result:
 
-          */
 
-         static getChainId(v) {
 
-             const bv = getBigInt(v, "v");
 
-             // The v is not an EIP-155 v, so it is the unspecified chain ID
 
-             if ((bv == BN_27$1) || (bv == BN_28$1)) {
 
-                 return BN_0$7;
 
-             }
 
-             // Bad value for an EIP-155 v
 
-             assertArgument(bv >= BN_35$1, "invalid EIP-155 v", "v", v);
 
-             return (bv - BN_35$1) / BN_2$3;
 
-         }
 
-         /**
 
-          *  Compute the ``v`` for a chain ID for a legacy EIP-155 transactions.
 
-          *
 
-          *  Legacy transactions which use [[link-eip-155]] hijack the ``v``
 
-          *  property to include the chain ID.
 
-          *
 
-          *  @example:
 
-          *    Signature.getChainIdV(5, 27)
 
-          *    //_result:
 
-          *
 
-          *    Signature.getChainIdV(5, 28)
 
-          *    //_result:
 
-          *
 
-          */
 
-         static getChainIdV(chainId, v) {
 
-             return (getBigInt(chainId) * BN_2$3) + BigInt(35 + v - 27);
 
-         }
 
-         /**
 
-          *  Compute the normalized legacy transaction ``v`` from a ``yParirty``,
 
-          *  a legacy transaction ``v`` or a legacy [[link-eip-155]] transaction.
 
-          *
 
-          *  @example:
 
-          *    // The values 0 and 1 imply v is actually yParity
 
-          *    Signature.getNormalizedV(0)
 
-          *    //_result:
 
-          *
 
-          *    // Legacy non-EIP-1559 transaction (i.e. 27 or 28)
 
-          *    Signature.getNormalizedV(27)
 
-          *    //_result:
 
-          *
 
-          *    // Legacy EIP-155 transaction (i.e. >= 35)
 
-          *    Signature.getNormalizedV(46)
 
-          *    //_result:
 
-          *
 
-          *    // Invalid values throw
 
-          *    Signature.getNormalizedV(5)
 
-          *    //_error:
 
-          */
 
-         static getNormalizedV(v) {
 
-             const bv = getBigInt(v);
 
-             if (bv === BN_0$7 || bv === BN_27$1) {
 
-                 return 27;
 
-             }
 
-             if (bv === BN_1$3 || bv === BN_28$1) {
 
-                 return 28;
 
-             }
 
-             assertArgument(bv >= BN_35$1, "invalid v", "v", v);
 
-             // Otherwise, EIP-155 v means odd is 27 and even is 28
 
-             return (bv & BN_1$3) ? 27 : 28;
 
-         }
 
-         /**
 
-          *  Creates a new [[Signature]].
 
-          *
 
-          *  If no %%sig%% is provided, a new [[Signature]] is created
 
-          *  with default values.
 
-          *
 
-          *  If %%sig%% is a string, it is parsed.
 
-          */
 
-         static from(sig) {
 
-             function assertError(check, message) {
 
-                 assertArgument(check, message, "signature", sig);
 
-             }
 
-             if (sig == null) {
 
-                 return new Signature(_guard$3, ZeroHash, ZeroHash, 27);
 
-             }
 
-             if (typeof (sig) === "string") {
 
-                 const bytes = getBytes(sig, "signature");
 
-                 if (bytes.length === 64) {
 
-                     const r = hexlify(bytes.slice(0, 32));
 
-                     const s = bytes.slice(32, 64);
 
-                     const v = (s[0] & 0x80) ? 28 : 27;
 
-                     s[0] &= 0x7f;
 
-                     return new Signature(_guard$3, r, hexlify(s), v);
 
-                 }
 
-                 if (bytes.length === 65) {
 
-                     const r = hexlify(bytes.slice(0, 32));
 
-                     const s = bytes.slice(32, 64);
 
-                     assertError((s[0] & 0x80) === 0, "non-canonical s");
 
-                     const v = Signature.getNormalizedV(bytes[64]);
 
-                     return new Signature(_guard$3, r, hexlify(s), v);
 
-                 }
 
-                 assertError(false, "invalid raw signature length");
 
-             }
 
-             if (sig instanceof Signature) {
 
-                 return sig.clone();
 
-             }
 
-             // Get r
 
-             const _r = sig.r;
 
-             assertError(_r != null, "missing r");
 
-             const r = toUint256(_r);
 
-             // Get s; by any means necessary (we check consistency below)
 
-             const s = (function (s, yParityAndS) {
 
-                 if (s != null) {
 
-                     return toUint256(s);
 
-                 }
 
-                 if (yParityAndS != null) {
 
-                     assertError(isHexString(yParityAndS, 32), "invalid yParityAndS");
 
-                     const bytes = getBytes(yParityAndS);
 
-                     bytes[0] &= 0x7f;
 
-                     return hexlify(bytes);
 
-                 }
 
-                 assertError(false, "missing s");
 
-             })(sig.s, sig.yParityAndS);
 
-             assertError((getBytes(s)[0] & 0x80) == 0, "non-canonical s");
 
-             // Get v; by any means necessary (we check consistency below)
 
-             const { networkV, v } = (function (_v, yParityAndS, yParity) {
 
-                 if (_v != null) {
 
-                     const v = getBigInt(_v);
 
-                     return {
 
-                         networkV: ((v >= BN_35$1) ? v : undefined),
 
-                         v: Signature.getNormalizedV(v)
 
-                     };
 
-                 }
 
-                 if (yParityAndS != null) {
 
-                     assertError(isHexString(yParityAndS, 32), "invalid yParityAndS");
 
-                     return { v: ((getBytes(yParityAndS)[0] & 0x80) ? 28 : 27) };
 
-                 }
 
-                 if (yParity != null) {
 
-                     switch (getNumber(yParity, "sig.yParity")) {
 
-                         case 0: return { v: 27 };
 
-                         case 1: return { v: 28 };
 
-                     }
 
-                     assertError(false, "invalid yParity");
 
-                 }
 
-                 assertError(false, "missing v");
 
-             })(sig.v, sig.yParityAndS, sig.yParity);
 
-             const result = new Signature(_guard$3, r, s, v);
 
-             if (networkV) {
 
-                 result.#networkV = networkV;
 
-             }
 
-             // If multiple of v, yParity, yParityAndS we given, check they match
 
-             assertError(sig.yParity == null || getNumber(sig.yParity, "sig.yParity") === result.yParity, "yParity mismatch");
 
-             assertError(sig.yParityAndS == null || sig.yParityAndS === result.yParityAndS, "yParityAndS mismatch");
 
-             return result;
 
-         }
 
-     }
 
-     /**
 
-      *  Add details about signing here.
 
-      *
 
-      *  @_subsection: api/crypto:Signing  [about-signing]
 
-      */
 
-     /**
 
-      *  A **SigningKey** provides high-level access to the elliptic curve
 
-      *  cryptography (ECC) operations and key management.
 
-      */
 
-     class SigningKey {
 
-         #privateKey;
 
-         /**
 
-          *  Creates a new **SigningKey** for %%privateKey%%.
 
-          */
 
-         constructor(privateKey) {
 
-             assertArgument(dataLength(privateKey) === 32, "invalid private key", "privateKey", "[REDACTED]");
 
-             this.#privateKey = hexlify(privateKey);
 
-         }
 
-         /**
 
-          *  The private key.
 
-          */
 
-         get privateKey() { return this.#privateKey; }
 
-         /**
 
-          *  The uncompressed public key.
 
-          *
 
-          * This will always begin with the prefix ``0x04`` and be 132
 
-          * characters long (the ``0x`` prefix and 130 hexadecimal nibbles).
 
-          */
 
-         get publicKey() { return SigningKey.computePublicKey(this.#privateKey); }
 
-         /**
 
-          *  The compressed public key.
 
-          *
 
-          *  This will always begin with either the prefix ``0x02`` or ``0x03``
 
-          *  and be 68 characters long (the ``0x`` prefix and 33 hexadecimal
 
-          *  nibbles)
 
-          */
 
-         get compressedPublicKey() { return SigningKey.computePublicKey(this.#privateKey, true); }
 
-         /**
 
-          *  Return the signature of the signed %%digest%%.
 
-          */
 
-         sign(digest) {
 
-             assertArgument(dataLength(digest) === 32, "invalid digest length", "digest", digest);
 
-             const sig = secp256k1.sign(getBytesCopy(digest), getBytesCopy(this.#privateKey), {
 
-                 lowS: true
 
-             });
 
-             return Signature.from({
 
-                 r: toBeHex(sig.r, 32),
 
-                 s: toBeHex(sig.s, 32),
 
-                 v: (sig.recovery ? 0x1c : 0x1b)
 
-             });
 
-         }
 
-         /**
 
-          *  Returns the [[link-wiki-ecdh]] shared secret between this
 
-          *  private key and the %%other%% key.
 
-          *
 
-          *  The %%other%% key may be any type of key, a raw public key,
 
-          *  a compressed/uncompressed pubic key or aprivate key.
 
-          *
 
-          *  Best practice is usually to use a cryptographic hash on the
 
-          *  returned value before using it as a symetric secret.
 
-          *
 
-          *  @example:
 
-          *    sign1 = new SigningKey(id("some-secret-1"))
 
-          *    sign2 = new SigningKey(id("some-secret-2"))
 
-          *
 
-          *    // Notice that privA.computeSharedSecret(pubB)...
 
-          *    sign1.computeSharedSecret(sign2.publicKey)
 
-          *    //_result:
 
-          *
 
-          *    // ...is equal to privB.computeSharedSecret(pubA).
 
-          *    sign2.computeSharedSecret(sign1.publicKey)
 
-          *    //_result:
 
-          */
 
-         computeSharedSecret(other) {
 
-             const pubKey = SigningKey.computePublicKey(other);
 
-             return hexlify(secp256k1.getSharedSecret(getBytesCopy(this.#privateKey), getBytes(pubKey), false));
 
-         }
 
-         /**
 
-          *  Compute the public key for %%key%%, optionally %%compressed%%.
 
-          *
 
-          *  The %%key%% may be any type of key, a raw public key, a
 
-          *  compressed/uncompressed public key or private key.
 
-          *
 
-          *  @example:
 
-          *    sign = new SigningKey(id("some-secret"));
 
-          *
 
-          *    // Compute the uncompressed public key for a private key
 
-          *    SigningKey.computePublicKey(sign.privateKey)
 
-          *    //_result:
 
-          *
 
-          *    // Compute the compressed public key for a private key
 
-          *    SigningKey.computePublicKey(sign.privateKey, true)
 
-          *    //_result:
 
-          *
 
-          *    // Compute the uncompressed public key
 
-          *    SigningKey.computePublicKey(sign.publicKey, false);
 
-          *    //_result:
 
-          *
 
-          *    // Compute the Compressed a public key
 
-          *    SigningKey.computePublicKey(sign.publicKey, true);
 
-          *    //_result:
 
-          */
 
-         static computePublicKey(key, compressed) {
 
-             let bytes = getBytes(key, "key");
 
-             // private key
 
-             if (bytes.length === 32) {
 
-                 const pubKey = secp256k1.getPublicKey(bytes, !!compressed);
 
-                 return hexlify(pubKey);
 
-             }
 
-             // raw public key; use uncompressed key with 0x04 prefix
 
-             if (bytes.length === 64) {
 
-                 const pub = new Uint8Array(65);
 
-                 pub[0] = 0x04;
 
-                 pub.set(bytes, 1);
 
-                 bytes = pub;
 
-             }
 
-             const point = secp256k1.ProjectivePoint.fromHex(bytes);
 
-             return hexlify(point.toRawBytes(compressed));
 
-         }
 
-         /**
 
-          *  Returns the public key for the private key which produced the
 
-          *  %%signature%% for the given %%digest%%.
 
-          *
 
-          *  @example:
 
-          *    key = new SigningKey(id("some-secret"))
 
-          *    digest = id("hello world")
 
-          *    sig = key.sign(digest)
 
-          *
 
-          *    // Notice the signer public key...
 
-          *    key.publicKey
 
-          *    //_result:
 
-          *
 
-          *    // ...is equal to the recovered public key
 
-          *    SigningKey.recoverPublicKey(digest, sig)
 
-          *    //_result:
 
-          *
 
-          */
 
-         static recoverPublicKey(digest, signature) {
 
-             assertArgument(dataLength(digest) === 32, "invalid digest length", "digest", digest);
 
-             const sig = Signature.from(signature);
 
-             let secpSig = secp256k1.Signature.fromCompact(getBytesCopy(concat([sig.r, sig.s])));
 
-             secpSig = secpSig.addRecoveryBit(sig.yParity);
 
-             const pubKey = secpSig.recoverPublicKey(getBytesCopy(digest));
 
-             assertArgument(pubKey != null, "invalid signautre for digest", "signature", signature);
 
-             return "0x" + pubKey.toHex(false);
 
-         }
 
-         /**
 
-          *  Returns the point resulting from adding the ellipic curve points
 
-          *  %%p0%% and %%p1%%.
 
-          *
 
-          *  This is not a common function most developers should require, but
 
-          *  can be useful for certain privacy-specific techniques.
 
-          *
 
-          *  For example, it is used by [[HDNodeWallet]] to compute child
 
-          *  addresses from parent public keys and chain codes.
 
-          */
 
-         static addPoints(p0, p1, compressed) {
 
-             const pub0 = secp256k1.ProjectivePoint.fromHex(SigningKey.computePublicKey(p0).substring(2));
 
-             const pub1 = secp256k1.ProjectivePoint.fromHex(SigningKey.computePublicKey(p1).substring(2));
 
-             return "0x" + pub0.add(pub1).toHex(!!compressed);
 
-         }
 
-     }
 
-     /**
 
-      *  A fundamental building block of Ethereum is the underlying
 
-      *  cryptographic primitives.
 
-      *
 
-      *  @_section: api/crypto:Cryptographic Functions   [about-crypto]
 
-      */
 
-     /**
 
-      *  Once called, prevents any future change to the underlying cryptographic
 
-      *  primitives using the ``.register`` feature for hooks.
 
-      */
 
-     function lock() {
 
-         computeHmac.lock();
 
-         keccak256.lock();
 
-         pbkdf2.lock();
 
-         randomBytes.lock();
 
-         ripemd160.lock();
 
-         scrypt.lock();
 
-         scryptSync.lock();
 
-         sha256.lock();
 
-         sha512.lock();
 
-         randomBytes.lock();
 
-     }
 
-     const BN_0$6 = BigInt(0);
 
-     const BN_36 = BigInt(36);
 
-     function getChecksumAddress(address) {
 
-         //    if (!isHexString(address, 20)) {
 
-         //        logger.throwArgumentError("invalid address", "address", address);
 
-         //    }
 
-         address = address.toLowerCase();
 
-         const chars = address.substring(2).split("");
 
-         const expanded = new Uint8Array(40);
 
-         for (let i = 0; i < 40; i++) {
 
-             expanded[i] = chars[i].charCodeAt(0);
 
-         }
 
-         const hashed = getBytes(keccak256(expanded));
 
-         for (let i = 0; i < 40; i += 2) {
 
-             if ((hashed[i >> 1] >> 4) >= 8) {
 
-                 chars[i] = chars[i].toUpperCase();
 
-             }
 
-             if ((hashed[i >> 1] & 0x0f) >= 8) {
 
-                 chars[i + 1] = chars[i + 1].toUpperCase();
 
-             }
 
-         }
 
-         return "0x" + chars.join("");
 
-     }
 
-     // See: https://en.wikipedia.org/wiki/International_Bank_Account_Number
 
-     // Create lookup table
 
-     const ibanLookup = {};
 
-     for (let i = 0; i < 10; i++) {
 
-         ibanLookup[String(i)] = String(i);
 
-     }
 
-     for (let i = 0; i < 26; i++) {
 
-         ibanLookup[String.fromCharCode(65 + i)] = String(10 + i);
 
-     }
 
-     // How many decimal digits can we process? (for 64-bit float, this is 15)
 
-     // i.e. Math.floor(Math.log10(Number.MAX_SAFE_INTEGER));
 
-     const safeDigits = 15;
 
-     function ibanChecksum(address) {
 
-         address = address.toUpperCase();
 
-         address = address.substring(4) + address.substring(0, 2) + "00";
 
-         let expanded = address.split("").map((c) => { return ibanLookup[c]; }).join("");
 
-         // Javascript can handle integers safely up to 15 (decimal) digits
 
-         while (expanded.length >= safeDigits) {
 
-             let block = expanded.substring(0, safeDigits);
 
-             expanded = parseInt(block, 10) % 97 + expanded.substring(block.length);
 
-         }
 
-         let checksum = String(98 - (parseInt(expanded, 10) % 97));
 
-         while (checksum.length < 2) {
 
-             checksum = "0" + checksum;
 
-         }
 
-         return checksum;
 
-     }
 
-     const Base36 = (function () {
 
-         const result = {};
 
-         for (let i = 0; i < 36; i++) {
 
-             const key = "0123456789abcdefghijklmnopqrstuvwxyz"[i];
 
-             result[key] = BigInt(i);
 
-         }
 
-         return result;
 
-     })();
 
-     function fromBase36(value) {
 
-         value = value.toLowerCase();
 
-         let result = BN_0$6;
 
-         for (let i = 0; i < value.length; i++) {
 
-             result = result * BN_36 + Base36[value[i]];
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  Returns a normalized and checksumed address for %%address%%.
 
-      *  This accepts non-checksum addresses, checksum addresses and
 
-      *  [[getIcapAddress]] formats.
 
-      *
 
-      *  The checksum in Ethereum uses the capitalization (upper-case
 
-      *  vs lower-case) of the characters within an address to encode
 
-      *  its checksum, which offers, on average, a checksum of 15-bits.
 
-      *
 
-      *  If %%address%% contains both upper-case and lower-case, it is
 
-      *  assumed to already be a checksum address and its checksum is
 
-      *  validated, and if the address fails its expected checksum an
 
-      *  error is thrown.
 
-      *
 
-      *  If you wish the checksum of %%address%% to be ignore, it should
 
-      *  be converted to lower-case (i.e. ``.toLowercase()``) before
 
-      *  being passed in. This should be a very rare situation though,
 
-      *  that you wish to bypass the safegaurds in place to protect
 
-      *  against an address that has been incorrectly copied from another
 
-      *  source.
 
-      *
 
-      *  @example:
 
-      *    // Adds the checksum (via upper-casing specific letters)
 
-      *    getAddress("0x8ba1f109551bd432803012645ac136ddd64dba72")
 
-      *    //_result:
 
-      *
 
-      *    // Converts ICAP address and adds checksum
 
-      *    getAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36");
 
-      *    //_result:
 
-      *
 
-      *    // Throws an error if an address contains mixed case,
 
-      *    // but the checksum fails
 
-      *    getAddress("0x8Ba1f109551bD432803012645Ac136ddd64DBA72")
 
-      *    //_error:
 
-      */
 
-     function getAddress(address) {
 
-         assertArgument(typeof (address) === "string", "invalid address", "address", address);
 
-         if (address.match(/^(0x)?[0-9a-fA-F]{40}$/)) {
 
-             // Missing the 0x prefix
 
-             if (!address.startsWith("0x")) {
 
-                 address = "0x" + address;
 
-             }
 
-             const result = getChecksumAddress(address);
 
-             // It is a checksummed address with a bad checksum
 
-             assertArgument(!address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) || result === address, "bad address checksum", "address", address);
 
-             return result;
 
-         }
 
-         // Maybe ICAP? (we only support direct mode)
 
-         if (address.match(/^XE[0-9]{2}[0-9A-Za-z]{30,31}$/)) {
 
-             // It is an ICAP address with a bad checksum
 
-             assertArgument(address.substring(2, 4) === ibanChecksum(address), "bad icap checksum", "address", address);
 
-             let result = fromBase36(address.substring(4)).toString(16);
 
-             while (result.length < 40) {
 
-                 result = "0" + result;
 
-             }
 
-             return getChecksumAddress("0x" + result);
 
-         }
 
-         assertArgument(false, "invalid address", "address", address);
 
-     }
 
-     /**
 
-      *  The [ICAP Address format](link-icap) format is an early checksum
 
-      *  format which attempts to be compatible with the banking
 
-      *  industry [IBAN format](link-wiki-iban) for bank accounts.
 
-      *
 
-      *  It is no longer common or a recommended format.
 
-      *
 
-      *  @example:
 
-      *    getIcapAddress("0x8ba1f109551bd432803012645ac136ddd64dba72");
 
-      *    //_result:
 
-      *
 
-      *    getIcapAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36");
 
-      *    //_result:
 
-      *
 
-      *    // Throws an error if the ICAP checksum is wrong
 
-      *    getIcapAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK37");
 
-      *    //_error:
 
-      */
 
-     function getIcapAddress(address) {
 
-         //let base36 = _base16To36(getAddress(address).substring(2)).toUpperCase();
 
-         let base36 = BigInt(getAddress(address)).toString(36).toUpperCase();
 
-         while (base36.length < 30) {
 
-             base36 = "0" + base36;
 
-         }
 
-         return "XE" + ibanChecksum("XE00" + base36) + base36;
 
-     }
 
-     // http://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed
 
-     /**
 
-      *  Returns the address that would result from a ``CREATE`` for %%tx%%.
 
-      *
 
-      *  This can be used to compute the address a contract will be
 
-      *  deployed to by an EOA when sending a deployment transaction (i.e.
 
-      *  when the ``to`` address is ``null``).
 
-      *
 
-      *  This can also be used to compute the address a contract will be
 
-      *  deployed to by a contract, by using the contract's address as the
 
-      *  ``to`` and the contract's nonce.
 
-      *
 
-      *  @example
 
-      *    from = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
 
-      *    nonce = 5;
 
-      *
 
-      *    getCreateAddress({ from, nonce });
 
-      *    //_result:
 
-      */
 
-     function getCreateAddress(tx) {
 
-         const from = getAddress(tx.from);
 
-         const nonce = getBigInt(tx.nonce, "tx.nonce");
 
-         let nonceHex = nonce.toString(16);
 
-         if (nonceHex === "0") {
 
-             nonceHex = "0x";
 
-         }
 
-         else if (nonceHex.length % 2) {
 
-             nonceHex = "0x0" + nonceHex;
 
-         }
 
-         else {
 
-             nonceHex = "0x" + nonceHex;
 
-         }
 
-         return getAddress(dataSlice(keccak256(encodeRlp([from, nonceHex])), 12));
 
-     }
 
-     /**
 
-      *  Returns the address that would result from a ``CREATE2`` operation
 
-      *  with the given %%from%%, %%salt%% and %%initCodeHash%%.
 
-      *
 
-      *  To compute the %%initCodeHash%% from a contract's init code, use
 
-      *  the [[keccak256]] function.
 
-      *
 
-      *  For a quick overview and example of ``CREATE2``, see [[link-ricmoo-wisps]].
 
-      *
 
-      *  @example
 
-      *    // The address of the contract
 
-      *    from = "0x8ba1f109551bD432803012645Ac136ddd64DBA72"
 
-      *
 
-      *    // The salt
 
-      *    salt = id("HelloWorld")
 
-      *
 
-      *    // The hash of the initCode
 
-      *    initCode = "0x6394198df16000526103ff60206004601c335afa6040516060f3";
 
-      *    initCodeHash = keccak256(initCode)
 
-      *
 
-      *    getCreate2Address(from, salt, initCodeHash)
 
-      *    //_result:
 
-      */
 
-     function getCreate2Address(_from, _salt, _initCodeHash) {
 
-         const from = getAddress(_from);
 
-         const salt = getBytes(_salt, "salt");
 
-         const initCodeHash = getBytes(_initCodeHash, "initCodeHash");
 
-         assertArgument(salt.length === 32, "salt must be 32 bytes", "salt", _salt);
 
-         assertArgument(initCodeHash.length === 32, "initCodeHash must be 32 bytes", "initCodeHash", _initCodeHash);
 
-         return getAddress(dataSlice(keccak256(concat(["0xff", from, salt, initCodeHash])), 12));
 
-     }
 
-     /**
 
-      *  Returns true if %%value%% is an object which implements the
 
-      *  [[Addressable]] interface.
 
-      *
 
-      *  @example:
 
-      *    // Wallets and AbstractSigner sub-classes
 
-      *    isAddressable(Wallet.createRandom())
 
-      *    //_result:
 
-      *
 
-      *    // Contracts
 
-      *    contract = new Contract("dai.tokens.ethers.eth", [ ], provider)
 
-      *    isAddressable(contract)
 
-      *    //_result:
 
-      */
 
-     function isAddressable(value) {
 
-         return (value && typeof (value.getAddress) === "function");
 
-     }
 
-     /**
 
-      *  Returns true if %%value%% is a valid address.
 
-      *
 
-      *  @example:
 
-      *    // Valid address
 
-      *    isAddress("0x8ba1f109551bD432803012645Ac136ddd64DBA72")
 
-      *    //_result:
 
-      *
 
-      *    // Valid ICAP address
 
-      *    isAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36")
 
-      *    //_result:
 
-      *
 
-      *    // Invalid checksum
 
-      *    isAddress("0x8Ba1f109551bD432803012645Ac136ddd64DBa72")
 
-      *    //_result:
 
-      *
 
-      *    // Invalid ICAP checksum
 
-      *    isAddress("0x8Ba1f109551bD432803012645Ac136ddd64DBA72")
 
-      *    //_result:
 
-      *
 
-      *    // Not an address (an ENS name requires a provided and an
 
-      *    // asynchronous API to access)
 
-      *    isAddress("ricmoo.eth")
 
-      *    //_result:
 
-      */
 
-     function isAddress(value) {
 
-         try {
 
-             getAddress(value);
 
-             return true;
 
-         }
 
-         catch (error) { }
 
-         return false;
 
-     }
 
-     async function checkAddress(target, promise) {
 
-         const result = await promise;
 
-         if (result == null || result === "0x0000000000000000000000000000000000000000") {
 
-             assert(typeof (target) !== "string", "unconfigured name", "UNCONFIGURED_NAME", { value: target });
 
-             assertArgument(false, "invalid AddressLike value; did not resolve to a value address", "target", target);
 
-         }
 
-         return getAddress(result);
 
-     }
 
-     /**
 
-      *  Resolves to an address for the %%target%%, which may be any
 
-      *  supported address type, an [[Addressable]] or a Promise which
 
-      *  resolves to an address.
 
-      *
 
-      *  If an ENS name is provided, but that name has not been correctly
 
-      *  configured a [[UnconfiguredNameError]] is thrown.
 
-      *
 
-      *  @example:
 
-      *    addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
 
-      *
 
-      *    // Addresses are return synchronously
 
-      *    resolveAddress(addr, provider)
 
-      *    //_result:
 
-      *
 
-      *    // Address promises are resolved asynchronously
 
-      *    resolveAddress(Promise.resolve(addr))
 
-      *    //_result:
 
-      *
 
-      *    // ENS names are resolved asynchronously
 
-      *    resolveAddress("dai.tokens.ethers.eth", provider)
 
-      *    //_result:
 
-      *
 
-      *    // Addressable objects are resolved asynchronously
 
-      *    contract = new Contract(addr, [ ])
 
-      *    resolveAddress(contract, provider)
 
-      *    //_result:
 
-      *
 
-      *    // Unconfigured ENS names reject
 
-      *    resolveAddress("nothing-here.ricmoo.eth", provider)
 
-      *    //_error:
 
-      *
 
-      *    // ENS names require a NameResolver object passed in
 
-      *    // (notice the provider was omitted)
 
-      *    resolveAddress("nothing-here.ricmoo.eth")
 
-      *    //_error:
 
-      */
 
-     function resolveAddress(target, resolver) {
 
-         if (typeof (target) === "string") {
 
-             if (target.match(/^0x[0-9a-f]{40}$/i)) {
 
-                 return getAddress(target);
 
-             }
 
-             assert(resolver != null, "ENS resolution requires a provider", "UNSUPPORTED_OPERATION", { operation: "resolveName" });
 
-             return checkAddress(target, resolver.resolveName(target));
 
-         }
 
-         else if (isAddressable(target)) {
 
-             return checkAddress(target, target.getAddress());
 
-         }
 
-         else if (target && typeof (target.then) === "function") {
 
-             return checkAddress(target, target);
 
-         }
 
-         assertArgument(false, "unsupported addressable value", "target", target);
 
-     }
 
-     /**
 
-      *  A Typed object allows a value to have its type explicitly
 
-      *  specified.
 
-      *
 
-      *  For example, in Solidity, the value ``45`` could represent a
 
-      *  ``uint8`` or a ``uint256``. The value ``0x1234`` could represent
 
-      *  a ``bytes2`` or ``bytes``.
 
-      *
 
-      *  Since JavaScript has no meaningful way to explicitly inform any
 
-      *  APIs which what the type is, this allows transparent interoperation
 
-      *  with Soldity.
 
-      *
 
-      *  @_subsection: api/abi:Typed Values
 
-      */
 
-     const _gaurd = {};
 
-     function n(value, width) {
 
-         let signed = false;
 
-         if (width < 0) {
 
-             signed = true;
 
-             width *= -1;
 
-         }
 
-         // @TODO: Check range is valid for value
 
-         return new Typed(_gaurd, `${signed ? "" : "u"}int${width}`, value, { signed, width });
 
-     }
 
-     function b(value, size) {
 
-         // @TODO: Check range is valid for value
 
-         return new Typed(_gaurd, `bytes${(size) ? size : ""}`, value, { size });
 
-     }
 
-     const _typedSymbol = Symbol.for("_ethers_typed");
 
-     /**
 
-      *  The **Typed** class to wrap values providing explicit type information.
 
-      */
 
-     class Typed {
 
-         /**
 
-          *  The type, as a Solidity-compatible type.
 
-          */
 
-         type;
 
-         /**
 
-          *  The actual value.
 
-          */
 
-         value;
 
-         #options;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         _typedSymbol;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(gaurd, type, value, options) {
 
-             if (options == null) {
 
-                 options = null;
 
-             }
 
-             assertPrivate(_gaurd, gaurd, "Typed");
 
-             defineProperties(this, { _typedSymbol, type, value });
 
-             this.#options = options;
 
-             // Check the value is valid
 
-             this.format();
 
-         }
 
-         /**
 
-          *  Format the type as a Human-Readable type.
 
-          */
 
-         format() {
 
-             if (this.type === "array") {
 
-                 throw new Error("");
 
-             }
 
-             else if (this.type === "dynamicArray") {
 
-                 throw new Error("");
 
-             }
 
-             else if (this.type === "tuple") {
 
-                 return `tuple(${this.value.map((v) => v.format()).join(",")})`;
 
-             }
 
-             return this.type;
 
-         }
 
-         /**
 
-          *  The default value returned by this type.
 
-          */
 
-         defaultValue() {
 
-             return 0;
 
-         }
 
-         /**
 
-          *  The minimum value for numeric types.
 
-          */
 
-         minValue() {
 
-             return 0;
 
-         }
 
-         /**
 
-          *  The maximum value for numeric types.
 
-          */
 
-         maxValue() {
 
-             return 0;
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard is this is a [[TypedBigInt]].
 
-          */
 
-         isBigInt() {
 
-             return !!(this.type.match(/^u?int[0-9]+$/));
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard is this is a [[TypedData]].
 
-          */
 
-         isData() {
 
-             return this.type.startsWith("bytes");
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard is this is a [[TypedString]].
 
-          */
 
-         isString() {
 
-             return (this.type === "string");
 
-         }
 
-         /**
 
-          *  Returns the tuple name, if this is a tuple. Throws otherwise.
 
-          */
 
-         get tupleName() {
 
-             if (this.type !== "tuple") {
 
-                 throw TypeError("not a tuple");
 
-             }
 
-             return this.#options;
 
-         }
 
-         // Returns the length of this type as an array
 
-         // - `null` indicates the length is unforced, it could be dynamic
 
-         // - `-1` indicates the length is dynamic
 
-         // - any other value indicates it is a static array and is its length
 
-         /**
 
-          *  Returns the length of the array type or ``-1`` if it is dynamic.
 
-          *
 
-          *  Throws if the type is not an array.
 
-          */
 
-         get arrayLength() {
 
-             if (this.type !== "array") {
 
-                 throw TypeError("not an array");
 
-             }
 
-             if (this.#options === true) {
 
-                 return -1;
 
-             }
 
-             if (this.#options === false) {
 
-                 return (this.value).length;
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  Returns a new **Typed** of %%type%% with the %%value%%.
 
-          */
 
-         static from(type, value) {
 
-             return new Typed(_gaurd, type, value);
 
-         }
 
-         /**
 
-          *  Return a new ``uint8`` type for %%v%%.
 
-          */
 
-         static uint8(v) { return n(v, 8); }
 
-         /**
 
-          *  Return a new ``uint16`` type for %%v%%.
 
-          */
 
-         static uint16(v) { return n(v, 16); }
 
-         /**
 
-          *  Return a new ``uint24`` type for %%v%%.
 
-          */
 
-         static uint24(v) { return n(v, 24); }
 
-         /**
 
-          *  Return a new ``uint32`` type for %%v%%.
 
-          */
 
-         static uint32(v) { return n(v, 32); }
 
-         /**
 
-          *  Return a new ``uint40`` type for %%v%%.
 
-          */
 
-         static uint40(v) { return n(v, 40); }
 
-         /**
 
-          *  Return a new ``uint48`` type for %%v%%.
 
-          */
 
-         static uint48(v) { return n(v, 48); }
 
-         /**
 
-          *  Return a new ``uint56`` type for %%v%%.
 
-          */
 
-         static uint56(v) { return n(v, 56); }
 
-         /**
 
-          *  Return a new ``uint64`` type for %%v%%.
 
-          */
 
-         static uint64(v) { return n(v, 64); }
 
-         /**
 
-          *  Return a new ``uint72`` type for %%v%%.
 
-          */
 
-         static uint72(v) { return n(v, 72); }
 
-         /**
 
-          *  Return a new ``uint80`` type for %%v%%.
 
-          */
 
-         static uint80(v) { return n(v, 80); }
 
-         /**
 
-          *  Return a new ``uint88`` type for %%v%%.
 
-          */
 
-         static uint88(v) { return n(v, 88); }
 
-         /**
 
-          *  Return a new ``uint96`` type for %%v%%.
 
-          */
 
-         static uint96(v) { return n(v, 96); }
 
-         /**
 
-          *  Return a new ``uint104`` type for %%v%%.
 
-          */
 
-         static uint104(v) { return n(v, 104); }
 
-         /**
 
-          *  Return a new ``uint112`` type for %%v%%.
 
-          */
 
-         static uint112(v) { return n(v, 112); }
 
-         /**
 
-          *  Return a new ``uint120`` type for %%v%%.
 
-          */
 
-         static uint120(v) { return n(v, 120); }
 
-         /**
 
-          *  Return a new ``uint128`` type for %%v%%.
 
-          */
 
-         static uint128(v) { return n(v, 128); }
 
-         /**
 
-          *  Return a new ``uint136`` type for %%v%%.
 
-          */
 
-         static uint136(v) { return n(v, 136); }
 
-         /**
 
-          *  Return a new ``uint144`` type for %%v%%.
 
-          */
 
-         static uint144(v) { return n(v, 144); }
 
-         /**
 
-          *  Return a new ``uint152`` type for %%v%%.
 
-          */
 
-         static uint152(v) { return n(v, 152); }
 
-         /**
 
-          *  Return a new ``uint160`` type for %%v%%.
 
-          */
 
-         static uint160(v) { return n(v, 160); }
 
-         /**
 
-          *  Return a new ``uint168`` type for %%v%%.
 
-          */
 
-         static uint168(v) { return n(v, 168); }
 
-         /**
 
-          *  Return a new ``uint176`` type for %%v%%.
 
-          */
 
-         static uint176(v) { return n(v, 176); }
 
-         /**
 
-          *  Return a new ``uint184`` type for %%v%%.
 
-          */
 
-         static uint184(v) { return n(v, 184); }
 
-         /**
 
-          *  Return a new ``uint192`` type for %%v%%.
 
-          */
 
-         static uint192(v) { return n(v, 192); }
 
-         /**
 
-          *  Return a new ``uint200`` type for %%v%%.
 
-          */
 
-         static uint200(v) { return n(v, 200); }
 
-         /**
 
-          *  Return a new ``uint208`` type for %%v%%.
 
-          */
 
-         static uint208(v) { return n(v, 208); }
 
-         /**
 
-          *  Return a new ``uint216`` type for %%v%%.
 
-          */
 
-         static uint216(v) { return n(v, 216); }
 
-         /**
 
-          *  Return a new ``uint224`` type for %%v%%.
 
-          */
 
-         static uint224(v) { return n(v, 224); }
 
-         /**
 
-          *  Return a new ``uint232`` type for %%v%%.
 
-          */
 
-         static uint232(v) { return n(v, 232); }
 
-         /**
 
-          *  Return a new ``uint240`` type for %%v%%.
 
-          */
 
-         static uint240(v) { return n(v, 240); }
 
-         /**
 
-          *  Return a new ``uint248`` type for %%v%%.
 
-          */
 
-         static uint248(v) { return n(v, 248); }
 
-         /**
 
-          *  Return a new ``uint256`` type for %%v%%.
 
-          */
 
-         static uint256(v) { return n(v, 256); }
 
-         /**
 
-          *  Return a new ``uint256`` type for %%v%%.
 
-          */
 
-         static uint(v) { return n(v, 256); }
 
-         /**
 
-          *  Return a new ``int8`` type for %%v%%.
 
-          */
 
-         static int8(v) { return n(v, -8); }
 
-         /**
 
-          *  Return a new ``int16`` type for %%v%%.
 
-          */
 
-         static int16(v) { return n(v, -16); }
 
-         /**
 
-          *  Return a new ``int24`` type for %%v%%.
 
-          */
 
-         static int24(v) { return n(v, -24); }
 
-         /**
 
-          *  Return a new ``int32`` type for %%v%%.
 
-          */
 
-         static int32(v) { return n(v, -32); }
 
-         /**
 
-          *  Return a new ``int40`` type for %%v%%.
 
-          */
 
-         static int40(v) { return n(v, -40); }
 
-         /**
 
-          *  Return a new ``int48`` type for %%v%%.
 
-          */
 
-         static int48(v) { return n(v, -48); }
 
-         /**
 
-          *  Return a new ``int56`` type for %%v%%.
 
-          */
 
-         static int56(v) { return n(v, -56); }
 
-         /**
 
-          *  Return a new ``int64`` type for %%v%%.
 
-          */
 
-         static int64(v) { return n(v, -64); }
 
-         /**
 
-          *  Return a new ``int72`` type for %%v%%.
 
-          */
 
-         static int72(v) { return n(v, -72); }
 
-         /**
 
-          *  Return a new ``int80`` type for %%v%%.
 
-          */
 
-         static int80(v) { return n(v, -80); }
 
-         /**
 
-          *  Return a new ``int88`` type for %%v%%.
 
-          */
 
-         static int88(v) { return n(v, -88); }
 
-         /**
 
-          *  Return a new ``int96`` type for %%v%%.
 
-          */
 
-         static int96(v) { return n(v, -96); }
 
-         /**
 
-          *  Return a new ``int104`` type for %%v%%.
 
-          */
 
-         static int104(v) { return n(v, -104); }
 
-         /**
 
-          *  Return a new ``int112`` type for %%v%%.
 
-          */
 
-         static int112(v) { return n(v, -112); }
 
-         /**
 
-          *  Return a new ``int120`` type for %%v%%.
 
-          */
 
-         static int120(v) { return n(v, -120); }
 
-         /**
 
-          *  Return a new ``int128`` type for %%v%%.
 
-          */
 
-         static int128(v) { return n(v, -128); }
 
-         /**
 
-          *  Return a new ``int136`` type for %%v%%.
 
-          */
 
-         static int136(v) { return n(v, -136); }
 
-         /**
 
-          *  Return a new ``int144`` type for %%v%%.
 
-          */
 
-         static int144(v) { return n(v, -144); }
 
-         /**
 
-          *  Return a new ``int52`` type for %%v%%.
 
-          */
 
-         static int152(v) { return n(v, -152); }
 
-         /**
 
-          *  Return a new ``int160`` type for %%v%%.
 
-          */
 
-         static int160(v) { return n(v, -160); }
 
-         /**
 
-          *  Return a new ``int168`` type for %%v%%.
 
-          */
 
-         static int168(v) { return n(v, -168); }
 
-         /**
 
-          *  Return a new ``int176`` type for %%v%%.
 
-          */
 
-         static int176(v) { return n(v, -176); }
 
-         /**
 
-          *  Return a new ``int184`` type for %%v%%.
 
-          */
 
-         static int184(v) { return n(v, -184); }
 
-         /**
 
-          *  Return a new ``int92`` type for %%v%%.
 
-          */
 
-         static int192(v) { return n(v, -192); }
 
-         /**
 
-          *  Return a new ``int200`` type for %%v%%.
 
-          */
 
-         static int200(v) { return n(v, -200); }
 
-         /**
 
-          *  Return a new ``int208`` type for %%v%%.
 
-          */
 
-         static int208(v) { return n(v, -208); }
 
-         /**
 
-          *  Return a new ``int216`` type for %%v%%.
 
-          */
 
-         static int216(v) { return n(v, -216); }
 
-         /**
 
-          *  Return a new ``int224`` type for %%v%%.
 
-          */
 
-         static int224(v) { return n(v, -224); }
 
-         /**
 
-          *  Return a new ``int232`` type for %%v%%.
 
-          */
 
-         static int232(v) { return n(v, -232); }
 
-         /**
 
-          *  Return a new ``int240`` type for %%v%%.
 
-          */
 
-         static int240(v) { return n(v, -240); }
 
-         /**
 
-          *  Return a new ``int248`` type for %%v%%.
 
-          */
 
-         static int248(v) { return n(v, -248); }
 
-         /**
 
-          *  Return a new ``int256`` type for %%v%%.
 
-          */
 
-         static int256(v) { return n(v, -256); }
 
-         /**
 
-          *  Return a new ``int256`` type for %%v%%.
 
-          */
 
-         static int(v) { return n(v, -256); }
 
-         /**
 
-          *  Return a new ``bytes1`` type for %%v%%.
 
-          */
 
-         static bytes1(v) { return b(v, 1); }
 
-         /**
 
-          *  Return a new ``bytes2`` type for %%v%%.
 
-          */
 
-         static bytes2(v) { return b(v, 2); }
 
-         /**
 
-          *  Return a new ``bytes3`` type for %%v%%.
 
-          */
 
-         static bytes3(v) { return b(v, 3); }
 
-         /**
 
-          *  Return a new ``bytes4`` type for %%v%%.
 
-          */
 
-         static bytes4(v) { return b(v, 4); }
 
-         /**
 
-          *  Return a new ``bytes5`` type for %%v%%.
 
-          */
 
-         static bytes5(v) { return b(v, 5); }
 
-         /**
 
-          *  Return a new ``bytes6`` type for %%v%%.
 
-          */
 
-         static bytes6(v) { return b(v, 6); }
 
-         /**
 
-          *  Return a new ``bytes7`` type for %%v%%.
 
-          */
 
-         static bytes7(v) { return b(v, 7); }
 
-         /**
 
-          *  Return a new ``bytes8`` type for %%v%%.
 
-          */
 
-         static bytes8(v) { return b(v, 8); }
 
-         /**
 
-          *  Return a new ``bytes9`` type for %%v%%.
 
-          */
 
-         static bytes9(v) { return b(v, 9); }
 
-         /**
 
-          *  Return a new ``bytes10`` type for %%v%%.
 
-          */
 
-         static bytes10(v) { return b(v, 10); }
 
-         /**
 
-          *  Return a new ``bytes11`` type for %%v%%.
 
-          */
 
-         static bytes11(v) { return b(v, 11); }
 
-         /**
 
-          *  Return a new ``bytes12`` type for %%v%%.
 
-          */
 
-         static bytes12(v) { return b(v, 12); }
 
-         /**
 
-          *  Return a new ``bytes13`` type for %%v%%.
 
-          */
 
-         static bytes13(v) { return b(v, 13); }
 
-         /**
 
-          *  Return a new ``bytes14`` type for %%v%%.
 
-          */
 
-         static bytes14(v) { return b(v, 14); }
 
-         /**
 
-          *  Return a new ``bytes15`` type for %%v%%.
 
-          */
 
-         static bytes15(v) { return b(v, 15); }
 
-         /**
 
-          *  Return a new ``bytes16`` type for %%v%%.
 
-          */
 
-         static bytes16(v) { return b(v, 16); }
 
-         /**
 
-          *  Return a new ``bytes17`` type for %%v%%.
 
-          */
 
-         static bytes17(v) { return b(v, 17); }
 
-         /**
 
-          *  Return a new ``bytes18`` type for %%v%%.
 
-          */
 
-         static bytes18(v) { return b(v, 18); }
 
-         /**
 
-          *  Return a new ``bytes19`` type for %%v%%.
 
-          */
 
-         static bytes19(v) { return b(v, 19); }
 
-         /**
 
-          *  Return a new ``bytes20`` type for %%v%%.
 
-          */
 
-         static bytes20(v) { return b(v, 20); }
 
-         /**
 
-          *  Return a new ``bytes21`` type for %%v%%.
 
-          */
 
-         static bytes21(v) { return b(v, 21); }
 
-         /**
 
-          *  Return a new ``bytes22`` type for %%v%%.
 
-          */
 
-         static bytes22(v) { return b(v, 22); }
 
-         /**
 
-          *  Return a new ``bytes23`` type for %%v%%.
 
-          */
 
-         static bytes23(v) { return b(v, 23); }
 
-         /**
 
-          *  Return a new ``bytes24`` type for %%v%%.
 
-          */
 
-         static bytes24(v) { return b(v, 24); }
 
-         /**
 
-          *  Return a new ``bytes25`` type for %%v%%.
 
-          */
 
-         static bytes25(v) { return b(v, 25); }
 
-         /**
 
-          *  Return a new ``bytes26`` type for %%v%%.
 
-          */
 
-         static bytes26(v) { return b(v, 26); }
 
-         /**
 
-          *  Return a new ``bytes27`` type for %%v%%.
 
-          */
 
-         static bytes27(v) { return b(v, 27); }
 
-         /**
 
-          *  Return a new ``bytes28`` type for %%v%%.
 
-          */
 
-         static bytes28(v) { return b(v, 28); }
 
-         /**
 
-          *  Return a new ``bytes29`` type for %%v%%.
 
-          */
 
-         static bytes29(v) { return b(v, 29); }
 
-         /**
 
-          *  Return a new ``bytes30`` type for %%v%%.
 
-          */
 
-         static bytes30(v) { return b(v, 30); }
 
-         /**
 
-          *  Return a new ``bytes31`` type for %%v%%.
 
-          */
 
-         static bytes31(v) { return b(v, 31); }
 
-         /**
 
-          *  Return a new ``bytes32`` type for %%v%%.
 
-          */
 
-         static bytes32(v) { return b(v, 32); }
 
-         /**
 
-          *  Return a new ``address`` type for %%v%%.
 
-          */
 
-         static address(v) { return new Typed(_gaurd, "address", v); }
 
-         /**
 
-          *  Return a new ``bool`` type for %%v%%.
 
-          */
 
-         static bool(v) { return new Typed(_gaurd, "bool", !!v); }
 
-         /**
 
-          *  Return a new ``bytes`` type for %%v%%.
 
-          */
 
-         static bytes(v) { return new Typed(_gaurd, "bytes", v); }
 
-         /**
 
-          *  Return a new ``string`` type for %%v%%.
 
-          */
 
-         static string(v) { return new Typed(_gaurd, "string", v); }
 
-         /**
 
-          *  Return a new ``array`` type for %%v%%, allowing %%dynamic%% length.
 
-          */
 
-         static array(v, dynamic) {
 
-             throw new Error("not implemented yet");
 
-         }
 
-         /**
 
-          *  Return a new ``tuple`` type for %%v%%, with the optional %%name%%.
 
-          */
 
-         static tuple(v, name) {
 
-             throw new Error("not implemented yet");
 
-         }
 
-         /**
 
-          *  Return a new ``uint8`` type for %%v%%.
 
-          */
 
-         static overrides(v) {
 
-             return new Typed(_gaurd, "overrides", Object.assign({}, v));
 
-         }
 
-         /**
 
-          *  Returns true only if %%value%% is a [[Typed]] instance.
 
-          */
 
-         static isTyped(value) {
 
-             return (value
 
-                 && typeof (value) === "object"
 
-                 && "_typedSymbol" in value
 
-                 && value._typedSymbol === _typedSymbol);
 
-         }
 
-         /**
 
-          *  If the value is a [[Typed]] instance, validates the underlying value
 
-          *  and returns it, otherwise returns value directly.
 
-          *
 
-          *  This is useful for functions that with to accept either a [[Typed]]
 
-          *  object or values.
 
-          */
 
-         static dereference(value, type) {
 
-             if (Typed.isTyped(value)) {
 
-                 if (value.type !== type) {
 
-                     throw new Error(`invalid type: expecetd ${type}, got ${value.type}`);
 
-                 }
 
-                 return value.value;
 
-             }
 
-             return value;
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class AddressCoder extends Coder {
 
-         constructor(localName) {
 
-             super("address", "address", localName, false);
 
-         }
 
-         defaultValue() {
 
-             return "0x0000000000000000000000000000000000000000";
 
-         }
 
-         encode(writer, _value) {
 
-             let value = Typed.dereference(_value, "string");
 
-             try {
 
-                 value = getAddress(value);
 
-             }
 
-             catch (error) {
 
-                 return this._throwError(error.message, _value);
 
-             }
 
-             return writer.writeValue(value);
 
-         }
 
-         decode(reader) {
 
-             return getAddress(toBeHex(reader.readValue(), 20));
 
-         }
 
-     }
 
-     /**
 
-      *  Clones the functionality of an existing Coder, but without a localName
 
-      *
 
-      *  @_ignore
 
-      */
 
-     class AnonymousCoder extends Coder {
 
-         coder;
 
-         constructor(coder) {
 
-             super(coder.name, coder.type, "_", coder.dynamic);
 
-             this.coder = coder;
 
-         }
 
-         defaultValue() {
 
-             return this.coder.defaultValue();
 
-         }
 
-         encode(writer, value) {
 
-             return this.coder.encode(writer, value);
 
-         }
 
-         decode(reader) {
 
-             return this.coder.decode(reader);
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     function pack(writer, coders, values) {
 
-         let arrayValues = [];
 
-         if (Array.isArray(values)) {
 
-             arrayValues = values;
 
-         }
 
-         else if (values && typeof (values) === "object") {
 
-             let unique = {};
 
-             arrayValues = coders.map((coder) => {
 
-                 const name = coder.localName;
 
-                 assert(name, "cannot encode object for signature with missing names", "INVALID_ARGUMENT", { argument: "values", info: { coder }, value: values });
 
-                 assert(!unique[name], "cannot encode object for signature with duplicate names", "INVALID_ARGUMENT", { argument: "values", info: { coder }, value: values });
 
-                 unique[name] = true;
 
-                 return values[name];
 
-             });
 
-         }
 
-         else {
 
-             assertArgument(false, "invalid tuple value", "tuple", values);
 
-         }
 
-         assertArgument(coders.length === arrayValues.length, "types/value length mismatch", "tuple", values);
 
-         let staticWriter = new Writer();
 
-         let dynamicWriter = new Writer();
 
-         let updateFuncs = [];
 
-         coders.forEach((coder, index) => {
 
-             let value = arrayValues[index];
 
-             if (coder.dynamic) {
 
-                 // Get current dynamic offset (for the future pointer)
 
-                 let dynamicOffset = dynamicWriter.length;
 
-                 // Encode the dynamic value into the dynamicWriter
 
-                 coder.encode(dynamicWriter, value);
 
-                 // Prepare to populate the correct offset once we are done
 
-                 let updateFunc = staticWriter.writeUpdatableValue();
 
-                 updateFuncs.push((baseOffset) => {
 
-                     updateFunc(baseOffset + dynamicOffset);
 
-                 });
 
-             }
 
-             else {
 
-                 coder.encode(staticWriter, value);
 
-             }
 
-         });
 
-         // Backfill all the dynamic offsets, now that we know the static length
 
-         updateFuncs.forEach((func) => { func(staticWriter.length); });
 
-         let length = writer.appendWriter(staticWriter);
 
-         length += writer.appendWriter(dynamicWriter);
 
-         return length;
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     function unpack(reader, coders) {
 
-         let values = [];
 
-         let keys = [];
 
-         // A reader anchored to this base
 
-         let baseReader = reader.subReader(0);
 
-         coders.forEach((coder) => {
 
-             let value = null;
 
-             if (coder.dynamic) {
 
-                 let offset = reader.readIndex();
 
-                 let offsetReader = baseReader.subReader(offset);
 
-                 try {
 
-                     value = coder.decode(offsetReader);
 
-                 }
 
-                 catch (error) {
 
-                     // Cannot recover from this
 
-                     if (isError(error, "BUFFER_OVERRUN")) {
 
-                         throw error;
 
-                     }
 
-                     value = error;
 
-                     value.baseType = coder.name;
 
-                     value.name = coder.localName;
 
-                     value.type = coder.type;
 
-                 }
 
-             }
 
-             else {
 
-                 try {
 
-                     value = coder.decode(reader);
 
-                 }
 
-                 catch (error) {
 
-                     // Cannot recover from this
 
-                     if (isError(error, "BUFFER_OVERRUN")) {
 
-                         throw error;
 
-                     }
 
-                     value = error;
 
-                     value.baseType = coder.name;
 
-                     value.name = coder.localName;
 
-                     value.type = coder.type;
 
-                 }
 
-             }
 
-             if (value == undefined) {
 
-                 throw new Error("investigate");
 
-             }
 
-             values.push(value);
 
-             keys.push(coder.localName || null);
 
-         });
 
-         return Result.fromItems(values, keys);
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class ArrayCoder extends Coder {
 
-         coder;
 
-         length;
 
-         constructor(coder, length, localName) {
 
-             const type = (coder.type + "[" + (length >= 0 ? length : "") + "]");
 
-             const dynamic = (length === -1 || coder.dynamic);
 
-             super("array", type, localName, dynamic);
 
-             defineProperties(this, { coder, length });
 
-         }
 
-         defaultValue() {
 
-             // Verifies the child coder is valid (even if the array is dynamic or 0-length)
 
-             const defaultChild = this.coder.defaultValue();
 
-             const result = [];
 
-             for (let i = 0; i < this.length; i++) {
 
-                 result.push(defaultChild);
 
-             }
 
-             return result;
 
-         }
 
-         encode(writer, _value) {
 
-             const value = Typed.dereference(_value, "array");
 
-             if (!Array.isArray(value)) {
 
-                 this._throwError("expected array value", value);
 
-             }
 
-             let count = this.length;
 
-             if (count === -1) {
 
-                 count = value.length;
 
-                 writer.writeValue(value.length);
 
-             }
 
-             assertArgumentCount(value.length, count, "coder array" + (this.localName ? (" " + this.localName) : ""));
 
-             let coders = [];
 
-             for (let i = 0; i < value.length; i++) {
 
-                 coders.push(this.coder);
 
-             }
 
-             return pack(writer, coders, value);
 
-         }
 
-         decode(reader) {
 
-             let count = this.length;
 
-             if (count === -1) {
 
-                 count = reader.readIndex();
 
-                 // Check that there is *roughly* enough data to ensure
 
-                 // stray random data is not being read as a length. Each
 
-                 // slot requires at least 32 bytes for their value (or 32
 
-                 // bytes as a link to the data). This could use a much
 
-                 // tighter bound, but we are erroring on the side of safety.
 
-                 assert(count * WordSize <= reader.dataLength, "insufficient data length", "BUFFER_OVERRUN", { buffer: reader.bytes, offset: count * WordSize, length: reader.dataLength });
 
-             }
 
-             let coders = [];
 
-             for (let i = 0; i < count; i++) {
 
-                 coders.push(new AnonymousCoder(this.coder));
 
-             }
 
-             return unpack(reader, coders);
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class BooleanCoder extends Coder {
 
-         constructor(localName) {
 
-             super("bool", "bool", localName, false);
 
-         }
 
-         defaultValue() {
 
-             return false;
 
-         }
 
-         encode(writer, _value) {
 
-             const value = Typed.dereference(_value, "bool");
 
-             return writer.writeValue(value ? 1 : 0);
 
-         }
 
-         decode(reader) {
 
-             return !!reader.readValue();
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class DynamicBytesCoder extends Coder {
 
-         constructor(type, localName) {
 
-             super(type, type, localName, true);
 
-         }
 
-         defaultValue() {
 
-             return "0x";
 
-         }
 
-         encode(writer, value) {
 
-             value = getBytesCopy(value);
 
-             let length = writer.writeValue(value.length);
 
-             length += writer.writeBytes(value);
 
-             return length;
 
-         }
 
-         decode(reader) {
 
-             return reader.readBytes(reader.readIndex(), true);
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class BytesCoder extends DynamicBytesCoder {
 
-         constructor(localName) {
 
-             super("bytes", localName);
 
-         }
 
-         decode(reader) {
 
-             return hexlify(super.decode(reader));
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class FixedBytesCoder extends Coder {
 
-         size;
 
-         constructor(size, localName) {
 
-             let name = "bytes" + String(size);
 
-             super(name, name, localName, false);
 
-             defineProperties(this, { size }, { size: "number" });
 
-         }
 
-         defaultValue() {
 
-             return ("0x0000000000000000000000000000000000000000000000000000000000000000").substring(0, 2 + this.size * 2);
 
-         }
 
-         encode(writer, _value) {
 
-             let data = getBytesCopy(Typed.dereference(_value, this.type));
 
-             if (data.length !== this.size) {
 
-                 this._throwError("incorrect data length", _value);
 
-             }
 
-             return writer.writeBytes(data);
 
-         }
 
-         decode(reader) {
 
-             return hexlify(reader.readBytes(this.size));
 
-         }
 
-     }
 
-     const Empty = new Uint8Array([]);
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class NullCoder extends Coder {
 
-         constructor(localName) {
 
-             super("null", "", localName, false);
 
-         }
 
-         defaultValue() {
 
-             return null;
 
-         }
 
-         encode(writer, value) {
 
-             if (value != null) {
 
-                 this._throwError("not null", value);
 
-             }
 
-             return writer.writeBytes(Empty);
 
-         }
 
-         decode(reader) {
 
-             reader.readBytes(0);
 
-             return null;
 
-         }
 
-     }
 
-     const BN_0$5 = BigInt(0);
 
-     const BN_1$2 = BigInt(1);
 
-     const BN_MAX_UINT256$1 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class NumberCoder extends Coder {
 
-         size;
 
-         signed;
 
-         constructor(size, signed, localName) {
 
-             const name = ((signed ? "int" : "uint") + (size * 8));
 
-             super(name, name, localName, false);
 
-             defineProperties(this, { size, signed }, { size: "number", signed: "boolean" });
 
-         }
 
-         defaultValue() {
 
-             return 0;
 
-         }
 
-         encode(writer, _value) {
 
-             let value = getBigInt(Typed.dereference(_value, this.type));
 
-             // Check bounds are safe for encoding
 
-             let maxUintValue = mask(BN_MAX_UINT256$1, WordSize * 8);
 
-             if (this.signed) {
 
-                 let bounds = mask(maxUintValue, (this.size * 8) - 1);
 
-                 if (value > bounds || value < -(bounds + BN_1$2)) {
 
-                     this._throwError("value out-of-bounds", _value);
 
-                 }
 
-                 value = toTwos(value, 8 * WordSize);
 
-             }
 
-             else if (value < BN_0$5 || value > mask(maxUintValue, this.size * 8)) {
 
-                 this._throwError("value out-of-bounds", _value);
 
-             }
 
-             return writer.writeValue(value);
 
-         }
 
-         decode(reader) {
 
-             let value = mask(reader.readValue(), this.size * 8);
 
-             if (this.signed) {
 
-                 value = fromTwos(value, this.size * 8);
 
-             }
 
-             return value;
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class StringCoder extends DynamicBytesCoder {
 
-         constructor(localName) {
 
-             super("string", localName);
 
-         }
 
-         defaultValue() {
 
-             return "";
 
-         }
 
-         encode(writer, _value) {
 
-             return super.encode(writer, toUtf8Bytes(Typed.dereference(_value, "string")));
 
-         }
 
-         decode(reader) {
 
-             return toUtf8String(super.decode(reader));
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     class TupleCoder extends Coder {
 
-         coders;
 
-         constructor(coders, localName) {
 
-             let dynamic = false;
 
-             const types = [];
 
-             coders.forEach((coder) => {
 
-                 if (coder.dynamic) {
 
-                     dynamic = true;
 
-                 }
 
-                 types.push(coder.type);
 
-             });
 
-             const type = ("tuple(" + types.join(",") + ")");
 
-             super("tuple", type, localName, dynamic);
 
-             defineProperties(this, { coders: Object.freeze(coders.slice()) });
 
-         }
 
-         defaultValue() {
 
-             const values = [];
 
-             this.coders.forEach((coder) => {
 
-                 values.push(coder.defaultValue());
 
-             });
 
-             // We only output named properties for uniquely named coders
 
-             const uniqueNames = this.coders.reduce((accum, coder) => {
 
-                 const name = coder.localName;
 
-                 if (name) {
 
-                     if (!accum[name]) {
 
-                         accum[name] = 0;
 
-                     }
 
-                     accum[name]++;
 
-                 }
 
-                 return accum;
 
-             }, {});
 
-             // Add named values
 
-             this.coders.forEach((coder, index) => {
 
-                 let name = coder.localName;
 
-                 if (!name || uniqueNames[name] !== 1) {
 
-                     return;
 
-                 }
 
-                 if (name === "length") {
 
-                     name = "_length";
 
-                 }
 
-                 if (values[name] != null) {
 
-                     return;
 
-                 }
 
-                 values[name] = values[index];
 
-             });
 
-             return Object.freeze(values);
 
-         }
 
-         encode(writer, _value) {
 
-             const value = Typed.dereference(_value, "tuple");
 
-             return pack(writer, this.coders, value);
 
-         }
 
-         decode(reader) {
 
-             return unpack(reader, this.coders);
 
-         }
 
-     }
 
-     /**
 
-      *  A simple hashing function which operates on UTF-8 strings to
 
-      *  compute an 32-byte identifier.
 
-      *
 
-      *  This simply computes the [UTF-8 bytes](toUtf8Bytes) and computes
 
-      *  the [[keccak256]].
 
-      *
 
-      *  @example:
 
-      *    id("hello world")
 
-      *    //_result:
 
-      */
 
-     function id(value) {
 
-         return keccak256(toUtf8Bytes(value));
 
-     }
 
-     // created 2023-09-25T01:01:55.148Z
 
-     // compressed base64-encoded blob for include-ens data
 
-     // source: https://github.com/adraffy/ens-normalize.js/blob/main/src/make.js
 
-     // see: https://github.com/adraffy/ens-normalize.js#security
 
-     // SHA-256: 0565ed049b9cf1614bb9e11ba7d8ac6a6fb96c893253d890f7e2b2884b9ded32
 
-     var COMPRESSED$1 = 'AEEUdwmgDS8BxQKKAP4BOgDjATAAngDUAIMAoABoAOAAagCOAEQAhABMAHIAOwA9ACsANgAmAGIAHgAuACgAJwAXAC0AGgAjAB8ALwAUACkAEgAeAAkAGwARABkAFgA5ACgALQArADcAFQApABAAHgAiABAAGgAeABMAGAUhBe8BFxREN8sF2wC5AK5HAW8ArQkDzQCuhzc3NzcBP68NEfMABQdHBuw5BV8FYAA9MzkI9r4ZBg7QyQAWA9CeOwLNCjcCjqkChuA/lm+RAsXTAoP6ASfnEQDytQFJAjWVCkeXAOsA6godAB/cwdAUE0WlBCN/AQUCQRjFD/MRBjHxDQSJbw0jBzUAswBxme+tnIcAYwabAysG8QAjAEMMmxcDqgPKQyDXCMMxA7kUQwD3NXOrAKmFIAAfBC0D3x4BJQDBGdUFAhEgVD8JnwmQJiNWYUzrg0oAGwAUAB0AFnNcACkAFgBP9h3gPfsDOWDKneY2ChglX1UDYD30ABsAFAAdABZzIGRAnwDD8wAjAEEMzRbDqgMB2sAFYwXqAtCnAsS4AwpUJKRtFHsadUz9AMMVbwLpABM1NJEX0ZkCgYMBEyMAxRVvAukAEzUBUFAtmUwSAy4DBTER33EftQHfSwB5MxJ/AjkWKQLzL8E/cwBB6QH9LQDPDtO9ASNriQC5DQANAwCK21EFI91zHwCoL9kBqQcHBwcHKzUDowBvAQohPvU3fAQgHwCyAc8CKQMA5zMSezr7ULgFmDp/LzVQBgEGAi8FYQVgt8AFcTtlQhpCWEmfe5tmZ6IAExsDzQ8t+X8rBKtTAltbAn0jsy8Bl6utPWMDTR8Ei2kRANkDBrNHNysDBzECQWUAcwFpJ3kAiyUhAJ0BUb8AL3EfAbfNAz81KUsFWwF3YQZtAm0A+VEfAzEJDQBRSQCzAQBlAHsAM70GD/v3IZWHBwARKQAxALsjTwHZAeMPEzmXgIHwABIAGQA8AEUAQDt3gdvIEGcQZAkGTRFMdEIVEwK0D64L7REdDNkq09PgADSxB/MDWwfzA1sDWwfzB/MDWwfzA1sDWwNbA1scEvAi28gQZw9QBHUFlgWTBN4IiyZREYkHMAjaVBV0JhxPA00BBCMtSSQ7mzMTJUpMFE0LCAQ2SmyvfUADTzGzVP2QqgPTMlc5dAkGHnkSqAAyD3skNb1OhnpPcagKU0+2tYdJak5vAsY6sEAACikJm2/Dd1YGRRAfJ6kQ+ww3AbkBPw3xS9wE9QY/BM0fgRkdD9GVoAipLeEM8SbnLqWAXiP5KocF8Uv4POELUVFsD10LaQnnOmeBUgMlAREijwrhDT0IcRD3Cs1vDekRSQc9A9lJngCpBwULFR05FbkmFGKwCw05ewb/GvoLkyazEy17AAXXGiUGUQEtGwMA0y7rhbRaNVwgT2MGBwspI8sUrFAkDSlAu3hMGh8HGSWtApVDdEqLUToelyH6PEENai4XUYAH+TwJGVMLhTyiRq9FEhHWPpE9TCJNTDAEOYMsMyePCdMPiQy9fHYBXQklCbUMdRM1ERs3yQg9Bx0xlygnGQglRplgngT7owP3E9UDDwVDCUUHFwO5HDETMhUtBRGBKNsC9zbZLrcCk1aEARsFzw8pH+MQVEfkDu0InwJpA4cl7wAxFSUAGyKfCEdnAGOP3FMJLs8Iy2pwI3gDaxTrZRF3B5UOWwerHDcVwxzlcMxeD4YMKKezCV8BeQmdAWME5wgNNV+MpCBFZ1eLXBifIGVBQ14AAjUMaRWjRMGHfAKPD28SHwE5AXcHPQ0FAnsR8RFvEJkI74YINbkz/DopBFMhhyAVCisDU2zSCysm/Qz8bQGnEmYDEDRBd/Jnr2C6KBgBBx0yyUFkIfULlk/RDKAaxRhGVDIZ6AfDA/ca9yfuQVsGAwOnBxc6UTPyBMELbQiPCUMATQ6nGwfbGG4KdYzUATWPAbudA1uVhwJzkwY7Bw8Aaw+LBX3pACECqwinAAkA0wNbAD0CsQehAB0AiUUBQQMrMwEl6QKTA5cINc8BmTMB9y0EH8cMGQD7O25OAsO1AoBuZqYF4VwCkgJNOQFRKQQJUktVA7N15QDfAE8GF+NLARmvTs8e50cB43MvAMsA/wAJOQcJRQHRAfdxALsBYws1Caa3uQFR7S0AhwAZbwHbAo0A4QA5AIP1AVcAUQVd/QXXAlNNARU1HC9bZQG/AyMBNwERAH0Gz5GpzQsjBHEH1wIQHxXlAu8yB7kFAyLjE9FCyQK94lkAMhoKPAqrCqpgX2Q3CjV2PVQAEh+sPss/UgVVO1c7XDtXO1w7VztcO1c7XDtXO1wDm8Pmw+YKcF9JYe8Mqg3YRMw6TRPfYFVgNhPMLbsUxRXSJVoZQRrAJwkl6FUNDwgt12Y0CDA0eRfAAEMpbINFY4oeNApPHOtTlVT8LR8AtUumM7MNsBsZREQFS3XxYi4WEgomAmSFAmJGX1GzAV83JAKh+wJonAJmDQKfiDgfDwJmPwJmKgRyBIMDfxcDfpY5Cjl7GzmGOicnAmwhAjI6OA4CbcsCbbLzjgM3a0kvAWsA4gDlAE4JB5wMkQECD8YAEbkCdzMCdqZDAnlPRwJ4viFg30WyRvcCfEMCeswCfQ0CfPRIBEiBZygALxlJXEpfGRtK0ALRBQLQ0EsrA4hTA4fqRMmRNgLypV0HAwOyS9JMMSkH001QTbMCi0MCitzFHwshR2sJuwKOOwKOYESbhQKO3QKOYHxRuFM5AQ5S2FSJApP/ApMQAO0AIFUiVbNV1AosHymZijLleGpFPz0Cl6MC77ZYJawAXSkClpMCloCgAK1ZsFoNhVEAPwKWuQKWUlxIXNUCmc8CmWhczl0LHQKcnznGOqECnBoCn58CnryOACETNS4TAp31Ap6WALlBYThh8wKe1wKgcgGtAp6jIwKeUqljzGQrKS8CJ7MCJoICoP8CoFDbAqYzAqXSAqgDAIECp/ZogGi1AAdNaiBq1QKs5wKssgKtawKtBgJXIQJV4AKx5dsDH1JsmwKywRECsuwbbORtZ21MYwMl0QK2YD9DbpQDKUkCuGICuUsZArkue3A6cOUCvR0DLbYDMhUCvoxyBgMzdQK+HnMmc1MCw88CwwhzhnRPOUl05AM8qwEDPJ4DPcMCxYACxksCxhSNAshtVQLISALJUwLJMgJkoQLd1nh9ZXiyeSlL1AMYp2cGAmH4GfeVKHsPXpZevxUCz28Cz3AzT1fW9xejAMqxAs93AS3uA04Wfk8JAtwrAtuOAtJTA1JgA1NjAQUDVZCAjUMEzxrxZEl5A4LSg5EC2ssC2eKEFIRNp0ADhqkAMwNkEoZ1Xf0AWQLfaQLevHd7AuIz7RgB8zQrAfSfAfLWiwLr9wLpdH0DAur9AuroAP1LAb0C7o0C66CWrpcHAu5DA4XkmH1w5HGlAvMHAG0DjhqZlwL3FwORcgOSiwL3nAL53QL4apogmq+/O5siA52HAv7+AR8APZ8gAZ+3AwWRA6ZuA6bdANXJAwZuoYyiCQ0DDE0BEwEjB3EGZb1rCQC/BG/DFY8etxEAG3k9ACcDNxJRA42DAWcrJQCM8wAlAOanC6OVCLsGI6fJBgCvBRnDBvElRUYFFoAFcD9GSDNCKUK8X3kZX8QAls0FOgCQVCGbwTsuYDoZutcONxjOGJHJ/gVfBWAFXwVgBWsFYAVfBWAFXwVgBV8FYAVfBWBOHQjfjW8KCgoKbF7xMwTRA7kGN8PDAMMEr8MA70gxFroFTj5xPnhCR0K+X30/X/AAWBkzswCNBsxzzASm70aCRS4rDDMeLz49fnXfcsH5GcoscQFz13Y4HwVnBXLJycnACNdRYwgICAqEXoWTxgA7P4kACxbZBu21Kw0AjMsTAwkVAOVtJUUsJ1JCuULESUArXy9gPi9AKwnJRQYKTD9LPoA+iT54PnkCkULEUUpDX9NWV3JVEjQAc1w3A3IBE3YnX+g7QiMJb6MKaiszRCUuQrNCxDPMCcwEX9EWJzYREBEEBwIHKn6l33JCNVIfybPJtAltydPUCmhBZw/tEKsZAJOVJU1CLRuxbUHOQAo7P0s+eEJHHA8SJVRPdGM0NVrpvBoKhfUlM0JHHGUQUhEWO1xLSj8MO0ucNAqJIzVCRxv9EFsqKyA4OQgNj2nwZgp5ZNFgE2A1K3YHS2AhQQojJmC7DgpzGG1WYFUZCQYHZO9gHWCdYIVgu2BTYJlwFh8GvRbcXbG8YgtDHrMBwzPVyQonHQgkCyYBgQJ0Ajc4nVqIAwGSCsBPIgDsK3SWEtIVBa5N8gGjAo+kVwVIZwD/AEUSCDweX4ITrRQsJ8K3TwBXFDwEAB0TvzVcAtoTS20RIwDgVgZ9BBImYgA5AL4Coi8LFnezOkCnIQFjAY4KBAPh9RcGsgZSBsEAJctdsWIRu2kTkQstRw7DAcMBKgpPBGIGMDAwKCYnKTQaLg4AKRSVAFwCdl+YUZ0JdicFD3lPAdt1F9ZZKCGxuE3yBxkFVGcA/wBFEgiCBwAOLHQSjxOtQDg1z7deFRMAZ8QTAGtKb1ApIiPHADkAvgKiLy1DFtYCmBiDAlDDWNB0eo7fpaMO/aEVRRv0ATEQZBIODyMEAc8JQhCbDRgzFD4TAEMAu9YBCgCsAOkAm5I3ABwAYxvONnR+MhXJAxgKQyxL2+kkJhMbhQKDBMkSsvF0AD9BNQ6uQC7WqSQHwxEAEEIu1hkhAH2z4iQPwyJPHNWpdyYBRSpnJALzoBAEVPPsH20MxA0CCEQKRgAFyAtFAlMNwwjEDUQJRArELtapMg7DDZgJIw+TGukEIwvDFkMAqAtDEMMMBhioe+QAO3MMRAACrgnEBSPY9Q0FDnbSBoMAB8MSYxkSxAEJAPIJAAB8FWMOFtMc/HcXwxhDAC7DAvOowwAewwJdKDKHAAHDAALrFUQVwwAbwyvzpWMWv8wA/ABpAy++bcYDUKPD0KhDCwKmJ1MAAmMA5+UZwxAagwipBRL/eADfw6fDGOMCGsOjk3l6BwOpo4sAEsMOGxMAA5sAbcMOAAvDp0MJGkMDwgipnNIPAwfIqUMGAOGDAAPzABXDAAcDAAnDAGmTABrDAA7DChjDjnEWAwABYwAOcwAuUyYABsMAF8MIKQANUgC6wy4AA8MADqMq8wCyYgAcIwAB8wqpAAXOCx0V4wAHowBCwwEKAGnDAAuDAB3DAAjDCakABdIAbqcZ3QCZCCkABdIAAAFDAAfjAB2jCCkABqIACYMAGzMAbSMA5sOIAAhjAAhDABTDBAkpAAbSAOOTAAlDC6kOzPtnAAdDAG6kQFAATwAKwwwAA0MACbUDPwAHIwAZgwACE6cDAAojAApDAAoDp/MGwwAJIwADEwAQQwgAFEMAEXMAD5MADfMADcMAGRMOFiMAFUMAbqMWuwHDAMIAE0MLAGkzEgDhUwACQwAEWgAXgwUjAAbYABjDBSYBgzBaAEFNALcQBxUMegAwMngBrA0IZgJ0KxQHBREPd1N0ZzKRJwaIHAZqNT4DqQq8BwngAB4DAwt2AX56T1ocKQNXAh1GATQGC3tOxYNagkgAMQA5CQADAQEAWxLjAIOYNAEzAH7tFRk6TglSAF8NAAlYAQ+S1ACAQwQorQBiAN4dAJ1wPyeTANVzuQDX3AIeEMp9eyMgXiUAEdkBkJizKltbVVAaRMqRAAEAhyQ/SDEz6BmfVwB6ATEsOClKIRcDOF0E/832AFNt5AByAnkCRxGCOs94NjXdAwINGBonDBwPALW2AwICAgAAAAAAAAYDBQMDARrUAwAtAAAAAgEGBgYGBgYFBQUFBQUEBQYHCAkEBQUFBQQAAAICAAAAIgCNAJAAlT0A6gC7ANwApEQAwgCyAK0AqADuAKYA2gCjAOcBCAEDAMcAgQBiANIA1AEDAN4A8gCQAKkBMQDqAN8A3AsBCQ8yO9ra2tq8xuLT1tRJOB0BUgFcNU0BWgFpAWgBWwFMUUlLbhMBUxsNEAs6PhMOACcUKy0vMj5AQENDQ0RFFEYGJFdXV1dZWVhZL1pbXVxcI2NnZ2ZoZypsbnZ1eHh4eHh4enp6enp6enp6enp8fH18e2IARPIASQCaAHgAMgBm+ACOAFcAVwA3AnbvAIsABfj4AGQAk/IAnwBPAGIAZP//sACFAIUAaQBWALEAJAC2AIMCQAJDAPwA5wD+AP4A6AD/AOkA6QDoAOYALwJ7AVEBQAE+AVQBPgE+AT4BOQE4ATgBOAEcAVgXADEQCAEAUx8SHgsdHhYAjgCWAKYAUQBqIAIxAHYAbwCXAxUDJzIDIUlGTzEAkQJPAMcCVwKkAMAClgKWApYClgKWApYCiwKWApYClgKWApYClgKVApUCmAKgApcClgKWApQClAKUApQCkgKVAnUB1AKXAp8ClgKWApUeAIETBQD+DQOfAmECOh8BVBg9AuIZEjMbAU4/G1WZAXusRAFpYQEFA0FPAQYAmTEeIJdyADFoAHEANgCRA5zMk/C2jGINwjMWygIZCaXdfDILBCs5dAE7YnQBugDlhoiHhoiGiYqKhouOjIaNkI6Ij4qQipGGkoaThpSSlYaWhpeKmIaZhpqGm4aci52QnoqfhuIC4XTpAt90AIp0LHSoAIsAdHQEQwRABEIERQRDBEkERgRBBEcESQRIBEQERgRJAJ5udACrA490ALxuAQ10ANFZdHQA13QCFHQA/mJ0AP4BIQD+APwA/AD9APwDhGZ03ASMK23HAP4A/AD8AP0A/CR0dACRYnQA/gCRASEA/gCRAvQA/gCRA4RmdNwEjCttxyR0AP9idAEhAP4A/gD8APwA/QD8AP8A/AD8AP0A/AOEZnTcBIwrbcckdHQAkWJ0ASEA/gCRAP4AkQL0AP4AkQOEZnTcBIwrbcckdAJLAT50AlIBQXQCU8l0dAJfdHQDpgL0A6YDpgOnA6cDpwOnA4RmdNwEjCttxyR0dACRYnQBIQOmAJEDpgCRAvQDpgCRA4RmdNwEjCttxyR0BDh0AJEEOQCRDpU5dSgCADR03gV2CwArdAEFAM5iCnR0AF1iAAYcOgp0dACRCnQAXAEIwWZ0CnRmdHQAkWZ0CnRmdEXgAFF03gp0dEY0tlT2u3SOAQTwscwhjZZKrhYcBSfFp9XNbKiVDOD2b+cpe4/Z17mQnbtzzhaeQtE2GGj0IDNTjRUSyTxxw/RPHW/+vS7d1NfRt9z9QPZg4X7QFfhCnkvgNPIItOsC2eV6hPannZNHlZ9xrwZXIMOlu3jSoQSq78WEjwLjw1ELSlF1aBvfzwk5ZX7AUvQzjPQKbDuQ+sm4wNOp4A6AdVuRS0t1y/DZpg4R6m7FNjM9HgvW7Bi88zaMjOo6lM8wtBBdj8LP4ylv3zCXPhebMKJc066o9sF71oFW/8JXu86HJbwDID5lzw5GWLR/LhT0Qqnp2JQxNZNfcbLIzPy+YypqRm/lBmGmex+82+PisxUumSeJkALIT6rJezxMH+CTJmQtt5uwTVbL3ptmjDUQzlSIvWi8Tl7ng1NpuRn1Ng4n14Qc+3Iil7OwkvNWogLSPkn3pihIFytyIGmMhOe3n1tWsuMy9BdKyqF4Z3v2SgggTL9KVvMXPnCbRe+oOuFFP3HejBG/w9gvmfNYvg6JuWia2lcSSN1uIjBktzoIazOHPJZ7kKHPz8mRWVdW3lA8WGF9dQF6Bm673boov3BUWDU2JNcahR23GtfHKLOz/viZ+rYnZFaIznXO67CYEJ1fXuTRpZhYZkKe54xeoagkNGLs+NTZHE0rX45/XvQ2RGADX6vcAvdxIUBV27wxGm2zjZo4X3ILgAlrOFheuZ6wtsvaIj4yLY7qqawlliaIcrz2G+c3vscAnCkCuMzMmZvMfu9lLwTvfX+3cVSyPdN9ZwgDZhfjRgNJcLiJ67b9xx8JHswprbiE3v9UphotAPIgnXVIN5KmMc0piXhc6cChPnN+MRhG9adtdttQTTwSIpl8I4/j//d3sz1326qTBTpPRM/Hgh3kzqEXs8ZAk4ErQhNO8hzrQ0DLkWMA/N+91tn2MdOJnWC2FCZehkQrwzwbKOjhvZsbM95QoeL9skYyMf4srVPVJSgg7pOLUtr/n9eT99oe9nLtFRpjA9okV2Kj8h9k5HaC0oivRD8VyXkJ81tcd4fHNXPCfloIQasxsuO18/46dR2jgul/UIet2G0kRvnyONMKhHs6J26FEoqSqd+rfYjeEGwHWVDpX1fh1jBBcKGMqRepju9Y00mDVHC+Xdij/j44rKfvfjGinNs1jO/0F3jB83XCDINN/HB84axlP+3E/klktRo+vl3U/aiyMJbIodE1XSsDn6UAzIoMtUObY2+k/4gY/l+AkZJ5Sj2vQrkyLm3FoxjhDX+31UXBFf9XrAH31fFqoBmDEZvhvvpnZ87N+oZEu7U9O/nnk+QWj3x8uyoRbEnf+O5UMr9i0nHP38IF5AvzrBW8YWBUR0mIAzIvndQq9N3v/Jto3aPjPXUPl8ASdPPyAp7jENf8bk7VMM9ol9XGmlBmeDMuGqt+WzuL6CXAxXjIhCPM5vACchgMJ/8XBGLO/D1isVvGhwwHHr1DLaI5mn2Jr/b1pUD90uciDaS8cXNDzCWvNmT/PhQe5e8nTnnnkt8Ds/SIjibcum/fqDhKopxAY8AkSrPn+IGDEKOO+U3XOP6djFs2H5N9+orhOahiQk5KnEUWa+CzkVzhp8bMHRbg81qhjjXuIKbHjSLSIBKWqockGtKinY+z4/RdBUF6pcc3JmnlxVcNgrI4SEzKUZSwcD2QCyxzKve+gAmg6ZuSRkpPFa6mfThu7LJNu3H5K42uCpNvPAsoedolKV/LHe/eJ+BbaG5MG0NaSGVPRUmNFMFFSSpXEcXwbVh7UETOZZtoVNRGOIbbkig3McEtR68cG0RZAoJevWYo7Dg/lZ1CQzblWeUvVHmr8fY4Nqd9JJiH/zEX24mJviH60fAyFr0A3c4bC1j3yZU60VgJxXn8JgJXLUIsiBnmKmMYz+7yBQFBvqb2eYnuW59joZBf56/wXvWIR4R8wTmV80i1mZy+S4+BUES+hzjk0uXpC///z/IlqHZ1monzlXp8aCfhGKMti73FI1KbL1q6IKO4fuBuZ59gagjn5xU79muMpHXg6S+e+gDM/U9BKLHbl9l6o8czQKl4RUkJJiqftQG2i3BMg/TQlUYFkJDYBOOvAugYuzYSDnZbDDd/aSd9x0Oe6F+bJcHfl9+gp6L5/TgA+BdFFovbfCrQ40s5vMPw8866pNX8zyFGeFWdxIpPVp9Rg1UPOVFbFZrvaFq/YAzHQgqMWpahMYfqHpmwXfHL1/kpYmGuHFwT55mQu0dylfNuq2Oq0hTMCPwqfxnuBIPLXfci4Y1ANy+1CUipQxld/izVh16WyG2Q0CQQ9NqtAnx1HCHwDj7sYxOSB0wopZSnOzxQOcExmxrVTF2BkOthVpGfuhaGECfCJpJKpjnihY+xOT2QJxN61+9K6QSqtv2Shr82I3jgJrqBg0wELFZPjvHpvzTtaJnLK6Vb97Yn933koO/saN7fsjwNKzp4l2lJVx2orjCGzC/4ZL4zCver6aQYtC5sdoychuFE6ufOiog+VWi5UDkbmvmtah/3aArEBIi39s5ILUnlFLgilcGuz9CQshEY7fw2ouoILAYPVT/gyAIq3TFAIwVsl+ktkRz/qGfnCDGrm5gsl/l9QdvCWGsjPz3dU7XuqKfdUrr/6XIgjp4rey6AJBmCmUJMjITHVdFb5m1p+dLMCL8t55zD42cmftmLEJC0Da04YiRCVUBLLa8D071/N5UBNBXDh0LFsmhV/5B5ExOB4j3WVG/S3lfK5o+V6ELHvy6RR9n4ac+VsK4VE4yphPvV+kG9FegTBH4ZRXL2HytUHCduJazB/KykjfetYxOXTLws267aGOd+I+JhKP//+VnXmS90OD/jvLcVu0asyqcuYN1mSb6XTlCkqv1vigZPIYwNF/zpWcT1GR/6aEIRjkh0yhg4LXJfaGobYJTY4JI58KiAKgmmgAKWdl5nYCeLqavRJGQNuYuZtZFGx+IkI4w4NS2xwbetNMunOjBu/hmKCI/w7tfiiyUd//4rbTeWt4izBY8YvGIN6vyKYmP/8X8wHKCeN+WRcKM70+tXKNGyevU9H2Dg5BsljnTf8YbsJ1TmMs74Ce2XlHisleguhyeg44rQOHZuw/6HTkhnnurK2d62q6yS7210SsAIaR+jXMQA+svkrLpsUY+F30Uw89uOdGAR6vo4FIME0EfVVeHTu6eKicfhSqOeXJhbftcd08sWEnNUL1C9fnprTgd83IMut8onVUF0hvqzZfHduPjbjwEXIcoYmy+P6tcJZHmeOv6VrvEdkHDJecjHuHeWANe79VG662qTjA/HCvumVv3qL+LrOcpqGps2ZGwQdFJ7PU4iuyRlBrwfO+xnPyr47s2cXVbWzAyznDiBGjCM3ksxjjqM62GE9C8f5U38kB3VjtabKp/nRdvMESPGDG90bWRLAt1Qk5DyLuazRR1YzdC1c+hZXvAWV8xA72S4A8B67vjVhbba3MMop293FeEXpe7zItMWrJG/LOH9ByOXmYnNJfjmfuX9KbrpgLOba4nZ+fl8Gbdv/ihv+6wFGKHCYrVwmhFC0J3V2bn2tIB1wCc1CST3d3X2OyxhguXcs4sm679UngzofuSeBewMFJboIQHbUh/m2JhW2hG9DIvG2t7yZIzKBTz9wBtnNC+2pCRYhSIuQ1j8xsz5VvqnyUIthvuoyyu7fNIrg/KQUVmGQaqkqZk/Vx5b33/gsEs8yX7SC1J+NV4icz6bvIE7C5G6McBaI8rVg56q5QBJWxn/87Q1sPK4+sQa8fLU5gXo4paaq4cOcQ4wR0VBHPGjKh+UlPCbA1nLXyEUX45qZ8J7/Ln4FPJE2TdzD0Z8MLSNQiykMMmSyOCiFfy84Rq60emYB2vD09KjYwsoIpeDcBDTElBbXxND72yhd9pC/1CMid/5HUMvAL27OtcIJDzNKpRPNqPOpyt2aPGz9QWIs9hQ9LiX5s8m9hjTUu/f7MyIatjjd+tSfQ3ufZxPpmJhTaBtZtKLUcfOCUqADuO+QoH8B9v6U+P0HV1GLQmtoNFTb3s74ivZgjES0qfK+8RdGgBbcCMSy8eBvh98+et1KIFqSe1KQPyXULBMTsIYnysIwiZBJYdI20vseV+wuJkcqGemehKjaAb9L57xZm3g2zX0bZ2xk/fU+bCo7TlnbW7JuF1YdURo/2Gw7VclDG1W7LOtas2LX4upifZ/23rzpsnY/ALfRgrcWP5hYmV9VxVOQA1fZvp9F2UNU+7d7xRyVm5wiLp3/0dlV7vdw1PMiZrbDAYzIVqEjRY2YU03sJhPnlwIPcZUG5ltL6S8XCxU1eYS5cjr34veBmXAvy7yN4ZjArIG0dfD/5UpBNlX1ZPoxJOwyqRi3wQWtOzd4oNKh0LkoTm8cwqgIfKhqqGOhwo71I+zXnMemTv2B2AUzABWyFztGgGULjDDzWYwJUVBTjKCn5K2QGMK1CQT7SzziOjo+BhAmqBjzuc3xYym2eedGeOIRJVyTwDw37iCMe4g5Vbnsb5ZBdxOAnMT7HU4DHpxWGuQ7GeiY30Cpbvzss55+5Km1YsbD5ea3NI9QNYIXol5apgSu9dZ8f8xS5dtHpido5BclDuLWY4lhik0tbJa07yJhH0BOyEut/GRbYTS6RfiTYWGMCkNpfSHi7HvdiTglEVHKZXaVhezH4kkXiIvKopYAlPusftpE4a5IZwvw1x/eLvoDIh/zpo9FiQInsTb2SAkKHV42XYBjpJDg4374XiVb3ws4qM0s9eSQ5HzsMU4OZJKuopFjBM+dAZEl8RUMx5uU2N486Kr141tVsGQfGjORYMCJAMsxELeNT4RmWjRcpdTGBwcx6XN9drWqPmJzcrGrH4+DRc7+n1w3kPZwu0BkNr6hQrqgo7JTB9A5kdJ/H7P4cWBMwsmuixAzJB3yrQpnGIq90lxAXLzDCdn1LPibsRt7rHNjgQBklRgPZ8vTbjXdgXrTWQsK5MdrXXQVPp0Rinq3frzZKJ0qD6Qhc40VzAraUXlob1gvkhK3vpmHgI6FRlQZNx6eRqkp0zy4AQlX813fAPtL3jMRaitGFFjo0zmErloC+h+YYdVQ6k4F/epxAoF0BmqEoKNTt6j4vQZNQ2BoqF9Vj53TOIoNmDiu9Xp15RkIgQIGcoLpfoIbenzpGUAtqFJp5W+LLnx38jHeECTJ/navKY1NWfN0sY1T8/pB8kIH3DU3DX+u6W3YwpypBMYOhbSxGjq84RZ84fWJow8pyHqn4S/9J15EcCMsXqrfwyd9mhiu3+rEo9pPpoJkdZqHjra4NvzFwuThNKy6hao/SlLw3ZADUcUp3w3SRVfW2rhl80zOgTYnKE0Hs2qp1J6H3xqPqIkvUDRMFDYyRbsFI3M9MEyovPk8rlw7/0a81cDVLmBsR2ze2pBuKb23fbeZC0uXoIvDppfTwIDxk1Oq2dGesGc+oJXWJLGkOha3CX+DUnzgAp9HGH9RsPZN63Hn4RMA5eSVhPHO+9RcRb/IOgtW31V1Q5IPGtoxPjC+MEJbVlIMYADd9aHYWUIQKopuPOHmoqSkubnAKnzgKHqgIOfW5RdAgotN6BN+O2ZYHkuemLnvQ8U9THVrS1RtLmKbcC7PeeDsYznvqzeg6VCNwmr0Yyx1wnLjyT84BZz3EJyCptD3yeueAyDWIs0L2qs/VQ3HUyqfrja0V1LdDzqAikeWuV4sc7RLIB69jEIBjCkyZedoUHqCrOvShVzyd73OdrJW0hPOuQv2qOoHDc9xVb6Yu6uq3Xqp2ZaH46A7lzevbxQEmfrzvAYSJuZ4WDk1Hz3QX1LVdiUK0EvlAGAYlG3Md30r7dcPN63yqBCIj25prpvZP0nI4+EgWoFG95V596CurXpKRBGRjQlHCvy5Ib/iW8nZJWwrET3mgd6mEhfP4KCuaLjopWs7h+MdXFdIv8dHQJgg1xi1eYqB0uDYjxwVmri0Sv5XKut/onqapC+FQiC2C1lvYJ9MVco6yDYsS3AANUfMtvtbYI2hfwZatiSsnoUeMZd34GVjkMMKA+XnjJpXgRW2SHTZplVowPmJsvXy6w3cfO1AK2dvtZEKTkC/TY9LFiKHCG0DnrMQdGm2lzlBHM9iEYynH2UcVMhUEjsc0oDBTgo2ZSQ1gzkAHeWeBXYFjYLuuf8yzTCy7/RFR81WDjXMbq2BOH5dURnxo6oivmxL3cKzKInlZkD31nvpHB9Kk7GfcfE1t+1V64b9LtgeJGlpRFxQCAqWJ5DoY77ski8gsOEOr2uywZaoO/NGa0X0y1pNQHBi3b2SUGNpcZxDT7rLbBf1FSnQ8guxGW3W+36BW0gBje4DOz6Ba6SVk0xiKgt+q2JOFyr4SYfnu+Ic1QZYIuwHBrgzr6UvOcSCzPTOo7D6IC4ISeS7zkl4h+2VoeHpnG/uWR3+ysNgPcOIXQbv0n4mr3BwQcdKJxgPSeyuP/z1Jjg4e9nUvoXegqQVIE30EHx5GHv+FAVUNTowYDJgyFhf5IvlYmEqRif6+WN1MkEJmDcQITx9FX23a4mxy1AQRsOHO/+eImX9l8EMJI3oPWzVXxSOeHU1dUWYr2uAA7AMb+vAEZSbU3qob9ibCyXeypEMpZ6863o6QPqlqGHZkuWABSTVNd4cOh9hv3qEpSx2Zy/DJMP6cItEmiBJ5PFqQnDEIt3NrA3COlOSgz43D7gpNFNJ5MBh4oFzhDPiglC2ypsNU4ISywY2erkyb1NC3Qh/IfWj0eDgZI4/ln8WPfBsT3meTjq1Uqt1E7Zl/qftqkx6aM9KueMCekSnMrcHj1CqTWWzEzPsZGcDe3Ue4Ws+XFYVxNbOFF8ezkvQGR6ZOtOLU2lQEnMBStx47vE6Pb7AYMBRj2OOfZXfisjJnpTfSNjo6sZ6qSvNxZNmDeS7Gk3yYyCk1HtKN2UnhMIjOXUzAqDv90lx9O/q/AT1ZMnit5XQe9wmQxnE/WSH0CqZ9/2Hy+Sfmpeg8RwsHI5Z8kC8H293m/LHVVM/BA7HaTJYg5Enk7M/xWpq0192ACfBai2LA/qrCjCr6Dh1BIMzMXINBmX96MJ5Hn2nxln/RXPFhwHxUmSV0EV2V0jm86/dxxuYSU1W7sVkEbN9EzkG0QFwPhyHKyb3t+Fj5WoUUTErcazE/N6EW6Lvp0d//SDPj7EV9UdJN+Amnf3Wwk3A0SlJ9Z00yvXZ7n3z70G47Hfsow8Wq1JXcfwnA+Yxa5mFsgV464KKP4T31wqIgzFPd3eCe3j5ory5fBF2hgCFyVFrLzI9eetNXvM7oQqyFgDo4CTp/hDV9NMX9JDHQ/nyHTLvZLNLF6ftn2OxjGm8+PqOwhxnPHWipkE/8wbtyri80Sr7pMNkQGMfo4ZYK9OcCC4ESVFFbLMIvlxSoRqWie0wxqnLfcLSXMSpMMQEJYDVObYsXIQNv4TGNwjq1kvT1UOkicTrG3IaBZ3XdScS3u8sgeZPVpOLkbiF940FjbCeNRINNvDbd01EPBrTCPpm12m43ze1bBB59Ia6Ovhnur/Nvx3IxwSWol+3H2qfCJR8df6aQf4v6WiONxkK+IqT4pKQrZK/LplgDI/PJZbOep8dtbV7oCr6CgfpWa8NczOkPx81iSHbsNhVSJBOtrLIMrL31LK9TqHqAbAHe0RLmmV806kRLDLNEhUEJfm9u0sxpkL93Zgd6rw+tqBfTMi59xqXHLXSHwSbSBl0EK0+loECOPtrl+/nsaFe197di4yUgoe4jKoAJDXc6DGDjrQOoFDWZJ9HXwt8xDrQP+7aRwWKWI1GF8s8O4KzxWBBcwnl3vnl1Oez3oh6Ea1vjR7/z7DDTrFtqU2W/KAEzAuXDNZ7MY73MF216dzdSbWmUp4lcm7keJfWaMHgut9x5C9mj66Z0lJ+yhsjVvyiWrfk1lzPOTdhG15Y7gQlXtacvI7qv/XNSscDwqkgwHT/gUsD5yB7LdRRvJxQGYINn9hTpodKFVSTPrtGvyQw+HlRFXIkodErAGu9Iy1YpfSPc3jkFh5CX3lPxv7aqjE/JAfTIpEjGb/H7MO0e2vsViSW1qa/Lmi4/n4DEI3g7lYrcanspDfEpKkdV1OjSLOy0BCUqVoECaB55vs06rXl4jqmLsPsFM/7vYJ0vrBhDCm/00A/H81l1uekJ/6Lml3Hb9+NKiLqATJmDpyzfYZFHumEjC662L0Bwkxi7E9U4cQA0XMVDuMYAIeLMPgQaMVOd8fmt5SflFIfuBoszeAw7ow5gXPE2Y/yBc/7jExARUf/BxIHQBF5Sn3i61w4z5xJdCyO1F1X3+3ax+JSvMeZ7S6QSKp1Fp/sjYz6Z+VgCZzibGeEoujryfMulH7Rai5kAft9ebcW50DyJr2uo2z97mTWIu45YsSnNSMrrNUuG1XsYBtD9TDYzQffKB87vWbkM4EbPAFgoBV4GQS+vtFDUqOFAoi1nTtmIOvg38N4hT2Sn8r8clmBCXspBlMBYTnrqFJGBT3wZOzAyJDre9dHH7+x7qaaKDOB4UQALD5ecS0DE4obubQEiuJZ0EpBVpLuYcce8Aa4PYd/V4DLDAJBYKQPCWTcrEaZ5HYbJi11Gd6hjGom1ii18VHYnG28NKpkz2UKVPxlhYSp8uZr367iOmoy7zsxehW9wzcy2zG0a80PBMCRQMb32hnaHeOR8fnNDzZhaNYhkOdDsBUZ3loDMa1YP0uS0cjUP3b/6DBlqmZOeNABDsLl5BI5QJups8uxAuWJdkUB/pO6Zax6tsg7fN5mjjDgMGngO+DPcKqiHIDbFIGudxtPTIyDi9SFMKBDcfdGQRv41q1AqmxgkVfJMnP8w/Bc7N9/TR6C7mGObFqFkIEom8sKi2xYqJLTCHK7cxzaZvqODo22c3wisBCP4HeAgcRbNPAsBkNRhSmD48dHupdBRw4mIvtS5oeF6zeT1KMCyhMnmhpkFAGWnGscoNkwvQ8ZM5lE/vgTHFYL99OuNxdFBxTEDd5v2qLR8y9WkXsWgG6kZNndFG+pO/UAkOCipqIhL3hq7cRSdrCq7YhUsTocEcnaFa6nVkhnSeRYUA1YO0z5itF9Sly3VlxYDw239TJJH6f3EUfYO5lb7bcFcz8Bp7Oo8QmnsUHOz/fagVUBtKEw1iT88j+aKkv8cscKNkMxjYr8344D1kFoZ7/td1W6LCNYN594301tUGRmFjAzeRg5vyoM1F6+bJZ/Q54jN/k8SFd3DxPTYaAUsivsBfgTn7Mx8H2SpPt4GOdYRnEJOH6jHM2p6SgB0gzIRq6fHxGMmSmqaPCmlfwxiuloaVIitLGN8wie2CDWhkzLoCJcODh7KIOAqbHEvXdUxaS4TTTs07Clzj/6GmVs9kiZDerMxEnhUB6QQPlcfqkG9882RqHoLiHGBoHfQuXIsAG8GTAtao2KVwRnvvam8jo1e312GQAKWEa4sUVEAMG4G6ckcONDwRcg1e2D3+ohXgY4UAWF8wHKQMrSnzCgfFpsxh+aHXMGtPQroQasRY4U6UdG0rz1Vjbka0MekOGRZQEvqQFlxseFor8zWFgHek3v29+WqN6gaK5gZOTOMZzpQIC1201LkMCXild3vWXSc5UX9xcFYfbRPzGFa1FDcPfPB/jUEq/FeGt419CI3YmBlVoHsa4KdcwQP5ZSwHHhFJ7/Ph/Rap/4vmG91eDwPP0lDfCDRCLszTqfzM71xpmiKi2HwS4WlqvGNwtvwF5Dqpn6KTq8ax00UMPkxDcZrEEEsIvHiUXXEphdb4GB4FymlPwBz4Gperqq5pW7TQ6/yNRhW8VT5NhuP0udlxo4gILq5ZxAZk8ZGh3g4CqxJlPKY7AQxupfUcVpWT5VItp1+30UqoyP4wWsRo3olRRgkWZZ2ZN6VC3OZFeXB8NbnUrSdikNptD1QiGuKkr8EmSR/AK9Rw+FF3s5uwuPbvHGiPeFOViltMK7AUaOsq9+x9cndk3iJEE5LKZRlWJbKOZweROzmPNVPkjE3K/TyA57Rs68TkZ3MR8akKpm7cFjnjPd/DdkWjgYoKHSr5Wu5ssoBYU4acRs5g2DHxUmdq8VXOXRbunD8QN0LhgkssgahcdoYsNvuXGUK/KXD/7oFb+VGdhqIn02veuM5bLudJOc2Ky0GMaG4W/xWBxIJcL7yliJOXOpx0AkBqUgzlDczmLT4iILXDxxtRR1oZa2JWFgiAb43obrJnG/TZC2KSK2wqOzRZTXavZZFMb1f3bXvVaNaK828w9TO610gk8JNf3gMfETzXXsbcvRGCG9JWQZ6+cDPqc4466Yo2RcKH+PILeKOqtnlbInR3MmBeGG3FH10yzkybuqEC2HSQwpA0An7d9+73BkDUTm30bZmoP/RGbgFN+GrCOfADgqr0WbI1a1okpFms8iHYw9hm0zUvlEMivBRxModrbJJ+9/p3jUdQQ9BCtQdxnOGrT5dzRUmw0593/mbRSdBg0nRvRZM5/E16m7ZHmDEtWhwvfdZCZ8J8M12W0yRMszXamWfQTwIZ4ayYktrnscQuWr8idp3PjT2eF/jmtdhIfcpMnb+IfZY2FebW6UY/AK3jP4u3Tu4zE4qlnQgLFbM19EBIsNf7KhjdbqQ/D6yiDb+NlEi2SKD+ivXVUK8ib0oBo366gXkR8ZxGjpJIDcEgZPa9TcYe0TIbiPl/rPUQDu3XBJ9X/GNq3FAUsKsll57DzaGMrjcT+gctp+9MLYXCq+sqP81eVQ0r9lt+gcQfZbACRbEjvlMskztZG8gbC8Qn9tt26Q7y7nDrbZq/LEz7kR6Jc6pg3N9rVX8Y5MJrGlML9p9lU4jbTkKqCveeZUJjHB03m2KRKR2TytoFkTXOLg7keU1s1lrPMQJpoOKLuAAC+y1HlJucU6ysB5hsXhvSPPLq5J7JtnqHKZ4vYjC4Vy8153QY+6780xDuGARsGbOs1WqzH0QS765rnSKEbbKlkO8oI/VDwUd0is13tKpqILu1mDJFNy/iJAWcvDgjxvusIT+PGz3ST/J9r9Mtfd0jpaGeiLYIqXc7DiHSS8TcjFVksi66PEkxW1z6ujbLLUGNNYnzOWpH8BZGK4bCK7iR+MbIv8ncDAz1u4StN3vTTzewr9IQjk9wxFxn+6N1ddKs0vffJiS08N3a4G1SVrlZ97Q/M+8G9fe5AP6d9/Qq4WRnORVhofPIKEdCr3llspUfE0oKIIYoByBRPh+bX1HLS3JWGJRhIvE1aW4NTd8ePi4Z+kXb+Z8snYfSNcqijhAgVsx4RCM54cXUiYkjeBmmC4ajOHrChoELscJJC7+9jjMjw5BagZKlgRMiSNYz7h7vvZIoQqbtQmspc0cUk1G/73iXtSpROl5wtLgQi0mW2Ex8i3WULhcggx6E1LMVHUsdc9GHI1PH3U2Ko0PyGdn9KdVOLm7FPBui0i9a0HpA60MsewVE4z8CAt5d401Gv6zXlIT5Ybit1VIA0FCs7wtvYreru1fUyW3oLAZ/+aTnZrOcYRNVA8spoRtlRoWflsRClFcgzkqiHOrf0/SVw+EpVaFlJ0g4Kxq1MMOmiQdpMNpte8lMMQqm6cIFXlnGbfJllysKDi+0JJMotkqgIxOSQgU9dn/lWkeVf8nUm3iwX2Nl3WDw9i6AUK3vBAbZZrcJpDQ/N64AVwjT07Jef30GSSmtNu2WlW7YoyW2FlWfZFQUwk867EdLYKk9VG6JgEnBiBxkY7LMo4YLQJJlAo9l/oTvJkSARDF/XtyAzM8O2t3eT/iXa6wDN3WewNmQHdPfsxChU/KtLG2Mn8i4ZqKdSlIaBZadxJmRzVS/o4yA65RTSViq60oa395Lqw0pzY4SipwE0SXXsKV+GZraGSkr/RW08wPRvqvSUkYBMA9lPx4m24az+IHmCbXA+0faxTRE9wuGeO06DIXa6QlKJ3puIyiuAVfPr736vzo2pBirS+Vxel3TMm3JKhz9o2ZoRvaFVpIkykb0Hcm4oHFBMcNSNj7/4GJt43ogonY2Vg4nsDQIWxAcorpXACzgBqQPjYsE/VUpXpwNManEru4NwMCFPkXvMoqvoeLN3qyu/N1eWEHttMD65v19l/0kH2mR35iv/FI+yjoHJ9gPMz67af3Mq/BoWXqu3rphiWMXVkmnPSEkpGpUI2h1MThideGFEOK6YZHPwYzMBvpNC7+ZHxPb7epfefGyIB4JzO9DTNEYnDLVVHdQyvOEVefrk6Uv5kTQYVYWWdqrdcIl7yljwwIWdfQ/y+2QB3eR/qxYObuYyB4gTbo2in4PzarU1sO9nETkmj9/AoxDA+JM3GMqQtJR4jtduHtnoCLxd1gQUscHRB/MoRYIEsP2pDZ9KvHgtlk1iTbWWbHhohwFEYX7y51fUV2nuUmnoUcqnWIQAAgl9LTVX+Bc0QGNEhChxHR4YjfE51PUdGfsSFE6ck7BL3/hTf9jLq4G1IafINxOLKeAtO7quulYvH5YOBc+zX7CrMgWnW47/jfRsWnJjYYoE7xMfWV2HN2iyIqLI';
 
-     const FENCED = new Map([[8217,"apostrophe"],[8260,"fraction slash"],[12539,"middle dot"]]);
 
-     const NSM_MAX = 4;
 
-     function decode_arithmetic(bytes) {
 
-     	let pos = 0;
 
-     	function u16() { return (bytes[pos++] << 8) | bytes[pos++]; }
 
-     	
 
-     	// decode the frequency table
 
-     	let symbol_count = u16();
 
-     	let total = 1;
 
-     	let acc = [0, 1]; // first symbol has frequency 1
 
-     	for (let i = 1; i < symbol_count; i++) {
 
-     		acc.push(total += u16());
 
-     	}
 
-     	// skip the sized-payload that the last 3 symbols index into
 
-     	let skip = u16();
 
-     	let pos_payload = pos;
 
-     	pos += skip;
 
-     	let read_width = 0;
 
-     	let read_buffer = 0; 
 
-     	function read_bit() {
 
-     		if (read_width == 0) {
 
-     			// this will read beyond end of buffer
 
-     			// but (undefined|0) => zero pad
 
-     			read_buffer = (read_buffer << 8) | bytes[pos++];
 
-     			read_width = 8;
 
-     		}
 
-     		return (read_buffer >> --read_width) & 1;
 
-     	}
 
-     	const N = 31;
 
-     	const FULL = 2**N;
 
-     	const HALF = FULL >>> 1;
 
-     	const QRTR = HALF >> 1;
 
-     	const MASK = FULL - 1;
 
-     	// fill register
 
-     	let register = 0;
 
-     	for (let i = 0; i < N; i++) register = (register << 1) | read_bit();
 
-     	let symbols = [];
 
-     	let low = 0;
 
-     	let range = FULL; // treat like a float
 
-     	while (true) {
 
-     		let value = Math.floor((((register - low + 1) * total) - 1) / range);
 
-     		let start = 0;
 
-     		let end = symbol_count;
 
-     		while (end - start > 1) { // binary search
 
-     			let mid = (start + end) >>> 1;
 
-     			if (value < acc[mid]) {
 
-     				end = mid;
 
-     			} else {
 
-     				start = mid;
 
-     			}
 
-     		}
 
-     		if (start == 0) break; // first symbol is end mark
 
-     		symbols.push(start);
 
-     		let a = low + Math.floor(range * acc[start]   / total);
 
-     		let b = low + Math.floor(range * acc[start+1] / total) - 1;
 
-     		while (((a ^ b) & HALF) == 0) {
 
-     			register = (register << 1) & MASK | read_bit();
 
-     			a = (a << 1) & MASK;
 
-     			b = (b << 1) & MASK | 1;
 
-     		}
 
-     		while (a & ~b & QRTR) {
 
-     			register = (register & HALF) | ((register << 1) & (MASK >>> 1)) | read_bit();
 
-     			a = (a << 1) ^ HALF;
 
-     			b = ((b ^ HALF) << 1) | HALF | 1;
 
-     		}
 
-     		low = a;
 
-     		range = 1 + b - a;
 
-     	}
 
-     	let offset = symbol_count - 4;
 
-     	return symbols.map(x => { // index into payload
 
-     		switch (x - offset) {
 
-     			case 3: return offset + 0x10100 + ((bytes[pos_payload++] << 16) | (bytes[pos_payload++] << 8) | bytes[pos_payload++]);
 
-     			case 2: return offset + 0x100 + ((bytes[pos_payload++] << 8) | bytes[pos_payload++]);
 
-     			case 1: return offset + bytes[pos_payload++];
 
-     			default: return x - 1;
 
-     		}
 
-     	});
 
-     }	
 
-     // returns an iterator which returns the next symbol
 
-     function read_payload(v) {
 
-     	let pos = 0;
 
-     	return () => v[pos++];
 
-     }
 
-     function read_compressed_payload(s) {
 
-     	return read_payload(decode_arithmetic(unsafe_atob(s)));
 
-     }
 
-     // unsafe in the sense:
 
-     // expected well-formed Base64 w/o padding 
 
-     // 20220922: added for https://github.com/adraffy/ens-normalize.js/issues/4
 
-     function unsafe_atob(s) {
 
-     	let lookup = [];
 
-     	[...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'].forEach((c, i) => lookup[c.charCodeAt(0)] = i);
 
-     	let n = s.length;
 
-     	let ret = new Uint8Array((6 * n) >> 3);
 
-     	for (let i = 0, pos = 0, width = 0, carry = 0; i < n; i++) {
 
-     		carry = (carry << 6) | lookup[s.charCodeAt(i)];
 
-     		width += 6;
 
-     		if (width >= 8) {
 
-     			ret[pos++] = (carry >> (width -= 8));
 
-     		}
 
-     	}
 
-     	return ret;
 
-     }
 
-     // eg. [0,1,2,3...] => [0,-1,1,-2,...]
 
-     function signed(i) { 
 
-     	return (i & 1) ? (~i >> 1) : (i >> 1);
 
-     }
 
-     function read_deltas(n, next) {
 
-     	let v = Array(n);
 
-     	for (let i = 0, x = 0; i < n; i++) v[i] = x += signed(next());
 
-     	return v;
 
-     }
 
-     // [123][5] => [0 3] [1 1] [0 0]
 
-     function read_sorted(next, prev = 0) {
 
-     	let ret = [];
 
-     	while (true) {
 
-     		let x = next();
 
-     		let n = next();
 
-     		if (!n) break;
 
-     		prev += x;
 
-     		for (let i = 0; i < n; i++) {
 
-     			ret.push(prev + i);
 
-     		}
 
-     		prev += n + 1;
 
-     	}
 
-     	return ret;
 
-     }
 
-     function read_sorted_arrays(next) {
 
-     	return read_array_while(() => { 
 
-     		let v = read_sorted(next);
 
-     		if (v.length) return v;
 
-     	});
 
-     }
 
-     // returns map of x => ys
 
-     function read_mapped(next) {
 
-     	let ret = [];
 
-     	while (true) {
 
-     		let w = next();
 
-     		if (w == 0) break;
 
-     		ret.push(read_linear_table(w, next));
 
-     	}
 
-     	while (true) {
 
-     		let w = next() - 1;
 
-     		if (w < 0) break;
 
-     		ret.push(read_replacement_table(w, next));
 
-     	}
 
-     	return ret.flat();
 
-     }
 
-     // read until next is falsy
 
-     // return array of read values
 
-     function read_array_while(next) {
 
-     	let v = [];
 
-     	while (true) {
 
-     		let x = next(v.length);
 
-     		if (!x) break;
 
-     		v.push(x);
 
-     	}
 
-     	return v;
 
-     }
 
-     // read w columns of length n
 
-     // return as n rows of length w
 
-     function read_transposed(n, w, next) {
 
-     	let m = Array(n).fill().map(() => []);
 
-     	for (let i = 0; i < w; i++) {
 
-     		read_deltas(n, next).forEach((x, j) => m[j].push(x));
 
-     	}
 
-     	return m;
 
-     }
 
-      
 
-     // returns [[x, ys], [x+dx, ys+dy], [x+2*dx, ys+2*dy], ...]
 
-     // where dx/dy = steps, n = run size, w = length of y
 
-     function read_linear_table(w, next) {
 
-     	let dx = 1 + next();
 
-     	let dy = next();
 
-     	let vN = read_array_while(next);
 
-     	let m = read_transposed(vN.length, 1+w, next);
 
-     	return m.flatMap((v, i) => {
 
-     		let [x, ...ys] = v;
 
-     		return Array(vN[i]).fill().map((_, j) => {
 
-     			let j_dy = j * dy;
 
-     			return [x + j * dx, ys.map(y => y + j_dy)];
 
-     		});
 
-     	});
 
-     }
 
-     // return [[x, ys...], ...]
 
-     // where w = length of y
 
-     function read_replacement_table(w, next) { 
 
-     	let n = 1 + next();
 
-     	let m = read_transposed(n, 1+w, next);
 
-     	return m.map(v => [v[0], v.slice(1)]);
 
-     }
 
-     function read_trie(next) {
 
-     	let ret = [];
 
-     	let sorted = read_sorted(next); 
 
-     	expand(decode([]), []);
 
-     	return ret; // not sorted
 
-     	function decode(Q) { // characters that lead into this node
 
-     		let S = next(); // state: valid, save, check
 
-     		let B = read_array_while(() => { // buckets leading to new nodes
 
-     			let cps = read_sorted(next).map(i => sorted[i]);
 
-     			if (cps.length) return decode(cps);
 
-     		});
 
-     		return {S, B, Q};
 
-     	}
 
-     	function expand({S, B}, cps, saved) {
 
-     		if (S & 4 && saved === cps[cps.length-1]) return;
 
-     		if (S & 2) saved = cps[cps.length-1];
 
-     		if (S & 1) ret.push(cps); 
 
-     		for (let br of B) {
 
-     			for (let cp of br.Q) {
 
-     				expand(br, [...cps, cp], saved);
 
-     			}
 
-     		}
 
-     	}
 
-     }
 
-     function hex_cp(cp) {
 
-     	return cp.toString(16).toUpperCase().padStart(2, '0');
 
-     }
 
-     function quote_cp(cp) {
 
-     	return `{${hex_cp(cp)}}`; // raffy convention: like "\u{X}" w/o the "\u"
 
-     }
 
-     /*
 
-     export function explode_cp(s) {
 
-     	return [...s].map(c => c.codePointAt(0));
 
-     }
 
-     */
 
-     function explode_cp(s) { // this is about 2x faster
 
-     	let cps = [];
 
-     	for (let pos = 0, len = s.length; pos < len; ) {
 
-     		let cp = s.codePointAt(pos);
 
-     		pos += cp < 0x10000 ? 1 : 2;
 
-     		cps.push(cp);
 
-     	}
 
-     	return cps;
 
-     }
 
-     function str_from_cps(cps) {
 
-     	const chunk = 4096;
 
-     	let len = cps.length;
 
-     	if (len < chunk) return String.fromCodePoint(...cps);
 
-     	let buf = [];
 
-     	for (let i = 0; i < len; ) {
 
-     		buf.push(String.fromCodePoint(...cps.slice(i, i += chunk)));
 
-     	}
 
-     	return buf.join('');
 
-     }
 
-     function compare_arrays(a, b) {
 
-     	let n = a.length;
 
-     	let c = n - b.length;
 
-     	for (let i = 0; c == 0 && i < n; i++) c = a[i] - b[i];
 
-     	return c;
 
-     }
 
-     // created 2023-09-25T01:01:55.148Z
 
-     // compressed base64-encoded blob for include-nf data
 
-     // source: https://github.com/adraffy/ens-normalize.js/blob/main/src/make.js
 
-     // see: https://github.com/adraffy/ens-normalize.js#security
 
-     // SHA-256: a974b6f8541fc29d919bc85118af0a44015851fab5343f8679cb31be2bdb209e
 
-     var COMPRESSED = 'AEUDTAHBCFQATQDRADAAcgAgADQAFAAsABQAHwAOACQADQARAAoAFwAHABIACAAPAAUACwAFAAwABAAQAAMABwAEAAoABQAIAAIACgABAAQAFAALAAIACwABAAIAAQAHAAMAAwAEAAsADAAMAAwACgANAA0AAwAKAAkABAAdAAYAZwDSAdsDJgC0CkMB8xhZAqfoC190UGcThgBurwf7PT09Pb09AjgJum8OjDllxHYUKXAPxzq6tABAxgK8ysUvWAgMPT09PT09PSs6LT2HcgWXWwFLoSMEEEl5RFVMKvO0XQ8ExDdJMnIgsj26PTQyy8FfEQ8AY8IPAGcEbwRwBHEEcgRzBHQEdQR2BHcEeAR6BHsEfAR+BIAEgfndBQoBYgULAWIFDAFiBNcE2ATZBRAFEQUvBdALFAsVDPcNBw13DYcOMA4xDjMB4BllHI0B2grbAMDpHLkQ7QHVAPRNQQFnGRUEg0yEB2uaJF8AJpIBpob5AERSMAKNoAXqaQLUBMCzEiACnwRZEkkVsS7tANAsBG0RuAQLEPABv9HICTUBXigPZwRBApMDOwAamhtaABqEAY8KvKx3LQ4ArAB8UhwEBAVSagD8AEFZADkBIadVj2UMUgx5Il4ANQC9AxIB1BlbEPMAs30CGxlXAhwZKQIECBc6EbsCoxngzv7UzRQA8M0BawL6ZwkN7wABAD33OQRcsgLJCjMCjqUChtw/km+NAsXPAoP2BT84PwURAK0RAvptb6cApQS/OMMey5HJS84UdxpxTPkCogVFITaTOwERAK5pAvkNBOVyA7q3BKlOJSALAgUIBRcEdASpBXqzABXFSWZOawLCOqw//AolCZdvv3dSBkEQGyelEPcMMwG1ATsN7UvYBPEGOwTJH30ZGQ/NlZwIpS3dDO0m4y6hgFoj9SqDBe1L9DzdC01RaA9ZC2UJ4zpjgU4DIQENIosK3Q05CG0Q8wrJaw3lEUUHOQPVSZoApQcBCxEdNRW1JhBirAsJOXcG+xr2C48mrxMpevwF0xohBk0BKRr/AM8u54WwWjFcHE9fBgMLJSPHFKhQIA0lQLd4SBobBxUlqQKRQ3BKh1E2HpMh9jw9DWYuE1F8B/U8BRlPC4E8nkarRQ4R0j6NPUgiSUwsBDV/LC8niwnPD4UMuXxyAVkJIQmxDHETMREXN8UIOQcZLZckJxUIIUaVYJoE958D8xPRAwsFPwlBBxMDtRwtEy4VKQUNgSTXAvM21S6zAo9WgAEXBcsPJR/fEFBH4A7pCJsCZQODJesALRUhABcimwhDYwBfj9hTBS7LCMdqbCN0A2cU52ERcweRDlcHpxwzFb8c4XDIXguGCCijrwlbAXUJmQFfBOMICTVbjKAgQWdTi1gYmyBhQT9d/AIxDGUVn0S9h3gCiw9rEhsBNQFzBzkNAQJ3Ee0RaxCVCOuGBDW1M/g6JQRPIYMgEQonA09szgsnJvkM+GkBoxJiAww0PXfuZ6tgtiQX/QcZMsVBYCHxC5JPzQycGsEYQlQuGeQHvwPzGvMn6kFXBf8DowMTOk0z7gS9C2kIiwk/AEkOoxcH1xhqCnGM0AExiwG3mQNXkYMCb48GNwcLAGcLhwV55QAdAqcIowAFAM8DVwA5Aq0HnQAZAIVBAT0DJy8BIeUCjwOTCDHLAZUvAfMpBBvDDBUA9zduSgLDsQKAamaiBd1YAo4CSTUBTSUEBU5HUQOvceEA2wBLBhPfRwEVq0rLGuNDAd9vKwDHAPsABTUHBUEBzQHzbQC3AV8LMQmis7UBTekpAIMAFWsB1wKJAN0ANQB/8QFTAE0FWfkF0wJPSQERMRgrV2EBuwMfATMBDQB5BsuNpckHHwRtB9MCEBsV4QLvLge1AQMi3xPNQsUCvd5VoWACZIECYkJbTa9bNyACofcCaJgCZgkCn4Q4GwsCZjsCZiYEbgR/A38TA36SOQY5dxc5gjojIwJsHQIyNjgKAm3HAm2u74ozZ0UrAWcA3gDhAEoFB5gMjQD+C8IADbUCdy8CdqI/AnlLQwJ4uh1c20WuRtcCfD8CesgCfQkCfPAFWQUgSABIfWMkAoFtAoAAAoAFAn+uSVhKWxUXSswC0QEC0MxLJwOITwOH5kTFkTIC8qFdAwMDrkvOTC0lA89NTE2vAos/AorYwRsHHUNnBbcCjjcCjlxAl4ECjtkCjlx4UbRTNQpS1FSFApP7ApMMAOkAHFUeVa9V0AYsGymVhjLheGZFOzkCl58C77JYIagAWSUClo8ClnycAKlZrFoJgU0AOwKWtQKWTlxEXNECmcsCmWRcyl0HGQKcmznCOp0CnBYCn5sCnriKAB0PMSoPAp3xAp6SALU9YTRh7wKe0wKgbgGpAp6fHwKeTqVjyGQnJSsCJ68CJn4CoPsCoEwCot0CocQCpi8Cpc4Cp/8AfQKn8mh8aLEAA0lqHGrRAqzjAqyuAq1nAq0CAlcdAlXcArHh1wMfTmyXArK9DQKy6Bds4G1jbUhfAyXNArZcOz9ukAMpRQK4XgK5RxUCuSp3cDZw4QK9GQK72nCWAzIRAr6IcgIDM3ECvhpzInNPAsPLAsMEc4J0SzVFdOADPKcDPJoDPb8CxXwCxkcCxhCJAshpUQLIRALJTwLJLgJknQLd0nh5YXiueSVL0AMYo2cCAmH0GfOVJHsLXpJeuxECz2sCz2wvS1PS8xOfAMatAs9zASnqA04SfksFAtwnAtuKAtJPA1JcA1NfAQEDVYyAiT8AyxbtYEWCHILTgs6DjQLaxwLZ3oQQhEmnPAOGpQAvA2QOhnFZ+QBVAt9lAt64c3cC4i/tFAHzMCcB9JsB8tKHAuvzAulweQLq+QLq5AD5RwG5Au6JAuuclqqXAwLuPwOF4Jh5cOBxoQLzAwBpA44WmZMC9xMDkW4DkocC95gC+dkC+GaaHJqruzebHgOdgwL++gEbADmfHJ+zAwWNA6ZqA6bZANHFAwZqoYiiBQkDDEkCwAA/AwDhQRdTARHzA2sHl2cFAJMtK7evvdsBiZkUfxEEOQH7KQUhDp0JnwCS/SlXxQL3AZ0AtwW5AG8LbUEuFCaNLgFDAYD8AbUmAHUDDgRtACwCFgyhAAAKAj0CagPdA34EkQEgRQUhfAoABQBEABMANhICdwEABdUDa+8KxQIA9wqfJ7+xt+UBkSFBQgHpFH8RNMCJAAQAGwBaAkUChIsABjpTOpSNbQC4Oo860ACNOME63AClAOgAywE6gTo7Ofw5+Tt2iTpbO56JOm85GAFWATMBbAUvNV01njWtNWY1dTW2NcU1gjWRNdI14TWeNa017jX9NbI1wTYCNhE1xjXVNhY2JzXeNe02LjY9Ni41LSE2OjY9Njw2yTcIBJA8VzY4Nt03IDcPNsogN4k3MAoEsDxnNiQ3GTdsOo03IULUQwdC4EMLHA8PCZsobShRVQYA6X8A6bABFCnXAukBowC9BbcAbwNzBL8MDAMMAQgDAAkKCwsLCQoGBAVVBI/DvwDz9b29kaUCb0QtsRTNLt4eGBcSHAMZFhYZEhYEARAEBUEcQRxBHEEcQRxBHEEaQRxBHEFCSTxBPElISUhBNkM2QTYbNklISVmBVIgBFLWZAu0BhQCjBcEAbykBvwGJAaQcEZ0ePCklMAAhMvAIMAL54gC7Bm8EescjzQMpARQpKgDUABavAj626xQAJP0A3etzuf4NNRA7efy2Z9NQrCnC0OSyANz5BBIbJ5IFDR6miIavYS6tprjjmuKebxm5C74Q225X1pkaYYPb6f1DK4k3xMEBb9S2WMjEibTNWhsRJIA+vwNVEiXTE5iXs/wezV66oFLfp9NZGYW+Gk19J2+bCT6Ye2w6LDYdgzKMUabk595eLBCXANz9HUpWbATq9vqXVx9XDg+Pc9Xp4+bsS005SVM/BJBM4687WUuf+Uj9dEi8aDNaPxtpbDxcG1THTImUMZq4UCaaNYpsVqraNyKLJXDYsFZ/5jl7bLRtO88t7P3xZaAxhb5OdPMXqsSkp1WCieG8jXm1U99+blvLlXzPCS+M93VnJCiK+09LfaSaBAVBomyDgJua8dfUzR7ga34IvR2Nvj+A9heJ6lsl1KG4NkI1032Cnff1m1wof2B9oHJK4bi6JkEdSqeNeiuo6QoZZincoc73/TH9SXF8sCE7XyuYyW8WSgbGFCjPV0ihLKhdPs08Tx82fYAkLLc4I2wdl4apY7GU5lHRFzRWJep7Ww3wbeA3qmd59/86P4xuNaqDpygXt6M85glSBHOCGgJDnt+pN9bK7HApMguX6+06RZNjzVmcZJ+wcUrJ9//bpRNxNuKpNl9uFds+S9tdx7LaM5ZkIrPj6nIU9mnbFtVbs9s/uLgl8MVczAwet+iOEzzBlYW7RCMgE6gyNLeq6+1tIx4dpgZnd0DksJS5f+JNDpwwcPNXaaVspq1fbQajOrJgK0ofKtJ1Ne90L6VO4MOl5S886p7u6xo7OLjG8TGL+HU1JXGJgppg4nNbNJ5nlzSpuPYy21JUEcUA94PoFiZfjZue+QnyQ80ekOuZVkxx4g+cvhJfHgNl4hy1/a6+RKcKlar/J29y//EztlbVPHVUeQ1zX86eQVAjR/M3dA9w4W8LfaXp4EgM85wOWasli837PzVMOnsLzR+k3o75/lRPAJSE1xAKQzEi5v10ke+VBvRt1cwQRMd+U5mLCTGVd6XiZtgBG5cDi0w22GKcVNvHiu5LQbZEDVtz0onn7k5+heuKXVsZtSzilkLRAUmjMXEMB3J9YC50XBxPiz53SC+EhnPl9WsKCv92SM/OFFIMJZYfl0WW8tIO3UxYcwdMAj7FSmgrsZ2aAZO03BOhP1bNNZItyXYQFTpC3SG1VuPDqH9GkiCDmE+JwxyIVSO5siDErAOpEXFgjy6PQtOVDj+s6e1r8heWVvmZnTciuf4EiNZzCAd7SOMhXERIOlsHIMG399i9aLTy3m2hRLZjJVDNLS53iGIK11dPqQt0zBDyg6qc7YqkDm2M5Ve6dCWCaCbTXX2rToaIgz6+zh4lYUi/+6nqcFMAkQJKHYLK0wYk5N9szV6xihDbDDFr45lN1K4aCXBq/FitPSud9gLt5ZVn+ZqGX7cwm2z5EGMgfFpIFyhGGuDPmso6TItTMwny+7uPnLCf4W6goFQFV0oQSsc9VfMmVLcLr6ZetDZbaSFTLqnSO/bIPjA3/zAUoqgGFAEQS4IhuMzEp2I3jJzbzkk/IEmyax+rhZTwd6f+CGtwPixu8IvzACquPWPREu9ZvGkUzpRwvRRuaNN6cr0W1wWits9ICdYJ7ltbgMiSL3sTPeufgNcVqMVWFkCPDH4jG2jA0XcVgQj62Cb29v9f/z/+2KbYvIv/zzjpQAPkliaVDzNrW57TZ/ZOyZD0nlfMmAIBIAGAI0D3k/mdN4xr9v85ZbZbbqfH2jGd5hUqNZWwl5SPfoGmfElmazUIeNL1j/mkF7VNAzTq4jNt8JoQ11NQOcmhprXoxSxfRGJ9LDEOAQ+dmxAQH90iti9e2u/MoeuaGcDTHoC+xsmEeWmxEKefQuIzHbpw5Tc5cEocboAD09oipWQhtTO1wivf/O+DRe2rpl/E9wlrzBorjJsOeG1B/XPW4EaJEFdNlECEZga5ZoGRHXgYouGRuVkm8tDESiEyFNo+3s5M5puSdTyUL2llnINVHEt91XUNW4ewdMgJ4boJfEyt/iY5WXqbA+A2Fkt5Z0lutiWhe9nZIyIUjyXDC3UsaG1t+eNx6z4W/OYoTB7A6x+dNSTOi9AInctbESqm5gvOLww7OWXPrmHwVZasrl4eD113pm+JtT7JVOvnCXqdzzdTRHgJ0PiGTFYW5Gvt9R9LD6Lzfs0v/TZZHSmyVNq7viIHE6DBK7Qp07Iz55EM8SYtQvZf/obBniTWi5C2/ovHfw4VndkE5XYdjOhCMRjDeOEfXeN/CwfGduiUIfsoFeUxXeQXba7c7972XNv8w+dTjjUM0QeNAReW+J014dKAD/McQYXT7c0GQPIkn3Ll6R7gGjuiQoZD0TEeEqQpKoZ15g/0OPQI17QiSv9AUROa/V/TQN3dvLArec3RrsYlvBm1b8LWzltdugsC50lNKYLEp2a+ZZYqPejULRlOJh5zj/LVMyTDvwKhMxxwuDkxJ1QpoNI0OTWLom4Z71SNzI9TV1iXJrIu9Wcnd+MCaAw8o1jSXd94YU/1gnkrC9BUEOtQvEIQ7g0i6h+KL2JKk8Ydl7HruvgWMSAmNe+LshGhV4qnWHhO9/RIPQzY1tHRj2VqOyNsDpK0cww+56AdDC4gsWwY0XxoucIWIqs/GcwnWqlaT0KPr8mbK5U94/301i1WLt4YINTVvCFBrFZbIbY8eycOdeJ2teD5IfPLCRg7jjcFTwlMFNl9zdh/o3E/hHPwj7BWg0MU09pPrBLbrCgm54A6H+I6v27+jL5gkjWg/iYdks9jbfVP5y/n0dlgWEMlKasl7JvFZd56LfybW1eeaVO0gxTfXZwD8G4SI116yx7UKVRgui6Ya1YpixqXeNLc8IxtAwCU5IhwQgn+NqHnRaDv61CxKhOq4pOX7M6pkA+Pmpd4j1vn6ACUALoLLc4vpXci8VidLxzm7qFBe7s+quuJs6ETYmnpgS3LwSZxPIltgBDXz8M1k/W2ySNv2f9/NPhxLGK2D21dkHeSGmenRT3Yqcdl0m/h3OYr8V+lXNYGf8aCCpd4bWjE4QIPj7vUKN4Nrfs7ML6Y2OyS830JCnofg/k7lpFpt4SqZc5HGg1HCOrHvOdC8bP6FGDbE/VV0mX4IakzbdS/op+Kt3G24/8QbBV7y86sGSQ/vZzU8FXs7u6jIvwchsEP2BpIhW3G8uWNwa3HmjfH/ZjhhCWvluAcF+nMf14ClKg5hGgtPLJ98ueNAkc5Hs2WZlk2QHvfreCK1CCGO6nMZVSb99VM/ajr8WHTte9JSmkXq/i/U943HEbdzW6Re/S88dKgg8pGOLlAeNiqrcLkUR3/aClFpMXcOUP3rmETcWSfMXZE3TUOi8i+fqRnTYLflVx/Vb/6GJ7eIRZUA6k3RYR3iFSK9c4iDdNwJuZL2FKz/IK5VimcNWEqdXjSoxSgmF0UPlDoUlNrPcM7ftmA8Y9gKiqKEHuWN+AZRIwtVSxye2Kf8rM3lhJ5XcBXU9n4v0Oy1RU2M+4qM8AQPVwse8ErNSob5oFPWxuqZnVzo1qB/IBxkM3EVUKFUUlO3e51259GgNcJbCmlvrdjtoTW7rChm1wyCKzpCTwozUUEOIcWLneRLgMXh+SjGSFkAllzbGS5HK7LlfCMRNRDSvbQPjcXaenNYxCvu2Qyznz6StuxVj66SgI0T8B6/sfHAJYZaZ78thjOSIFumNWLQbeZixDCCC+v0YBtkxiBB3jefHqZ/dFHU+crbj6OvS1x/JDD7vlm7zOVPwpUC01nhxZuY/63E7g';
 
-     // https://unicode.org/reports/tr15/
 
-     // for reference implementation
 
-     // see: /derive/nf.js
 
-     // algorithmic hangul
 
-     // https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf (page 144)
 
-     const S0 = 0xAC00;
 
-     const L0 = 0x1100;
 
-     const V0 = 0x1161;
 
-     const T0 = 0x11A7;
 
-     const L_COUNT = 19;
 
-     const V_COUNT = 21;
 
-     const T_COUNT = 28;
 
-     const N_COUNT = V_COUNT * T_COUNT;
 
-     const S_COUNT = L_COUNT * N_COUNT;
 
-     const S1 = S0 + S_COUNT;
 
-     const L1 = L0 + L_COUNT;
 
-     const V1 = V0 + V_COUNT;
 
-     const T1$1 = T0 + T_COUNT;
 
-     function unpack_cc(packed) {
 
-     	return (packed >> 24) & 0xFF;
 
-     }
 
-     function unpack_cp(packed) {
 
-     	return packed & 0xFFFFFF;
 
-     }
 
-     let SHIFTED_RANK, EXCLUSIONS, DECOMP, RECOMP;
 
-     function init$1() {
 
-     	//console.time('nf');
 
-     	let r = read_compressed_payload(COMPRESSED);
 
-     	SHIFTED_RANK = new Map(read_sorted_arrays(r).flatMap((v, i) => v.map(x => [x, (i+1) << 24]))); // pre-shifted
 
-     	EXCLUSIONS = new Set(read_sorted(r));
 
-     	DECOMP = new Map();
 
-     	RECOMP = new Map();
 
-     	for (let [cp, cps] of read_mapped(r)) {
 
-     		if (!EXCLUSIONS.has(cp) && cps.length == 2) {
 
-     			let [a, b] = cps;
 
-     			let bucket = RECOMP.get(a);
 
-     			if (!bucket) {
 
-     				bucket = new Map();
 
-     				RECOMP.set(a, bucket);
 
-     			}
 
-     			bucket.set(b, cp);
 
-     		}
 
-     		DECOMP.set(cp, cps.reverse()); // stored reversed
 
-     	}
 
-     	//console.timeEnd('nf');
 
-     	// 20230905: 11ms
 
-     }
 
-     function is_hangul(cp) {
 
-     	return cp >= S0 && cp < S1;
 
-     }
 
-     function compose_pair(a, b) {
 
-     	if (a >= L0 && a < L1 && b >= V0 && b < V1) {
 
-     		return S0 + (a - L0) * N_COUNT + (b - V0) * T_COUNT;
 
-     	} else if (is_hangul(a) && b > T0 && b < T1$1 && (a - S0) % T_COUNT == 0) {
 
-     		return a + (b - T0);
 
-     	} else {
 
-     		let recomp = RECOMP.get(a);
 
-     		if (recomp) {
 
-     			recomp = recomp.get(b);
 
-     			if (recomp) {
 
-     				return recomp;
 
-     			}
 
-     		}
 
-     		return -1;
 
-     	}
 
-     }
 
-     function decomposed(cps) {
 
-     	if (!SHIFTED_RANK) init$1();
 
-     	let ret = [];
 
-     	let buf = [];
 
-     	let check_order = false;
 
-     	function add(cp) {
 
-     		let cc = SHIFTED_RANK.get(cp);
 
-     		if (cc) {
 
-     			check_order = true;
 
-     			cp |= cc;
 
-     		}
 
-     		ret.push(cp);
 
-     	}
 
-     	for (let cp of cps) {
 
-     		while (true) {
 
-     			if (cp < 0x80) {
 
-     				ret.push(cp);
 
-     			} else if (is_hangul(cp)) {
 
-     				let s_index = cp - S0;
 
-     				let l_index = s_index / N_COUNT | 0;
 
-     				let v_index = (s_index % N_COUNT) / T_COUNT | 0;
 
-     				let t_index = s_index % T_COUNT;
 
-     				add(L0 + l_index);
 
-     				add(V0 + v_index);
 
-     				if (t_index > 0) add(T0 + t_index);
 
-     			} else {
 
-     				let mapped = DECOMP.get(cp);
 
-     				if (mapped) {
 
-     					buf.push(...mapped);
 
-     				} else {
 
-     					add(cp);
 
-     				}
 
-     			}
 
-     			if (!buf.length) break;
 
-     			cp = buf.pop();
 
-     		}
 
-     	}
 
-     	if (check_order && ret.length > 1) {
 
-     		let prev_cc = unpack_cc(ret[0]);
 
-     		for (let i = 1; i < ret.length; i++) {
 
-     			let cc = unpack_cc(ret[i]);
 
-     			if (cc == 0 || prev_cc <= cc) {
 
-     				prev_cc = cc;
 
-     				continue;
 
-     			}
 
-     			let j = i-1;
 
-     			while (true) {
 
-     				let tmp = ret[j+1];
 
-     				ret[j+1] = ret[j];
 
-     				ret[j] = tmp;
 
-     				if (!j) break;
 
-     				prev_cc = unpack_cc(ret[--j]);
 
-     				if (prev_cc <= cc) break;
 
-     			}
 
-     			prev_cc = unpack_cc(ret[i]);
 
-     		}
 
-     	}
 
-     	return ret;
 
-     }
 
-     function composed_from_decomposed(v) {
 
-     	let ret = [];
 
-     	let stack = [];
 
-     	let prev_cp = -1;
 
-     	let prev_cc = 0;
 
-     	for (let packed of v) {
 
-     		let cc = unpack_cc(packed);
 
-     		let cp = unpack_cp(packed);
 
-     		if (prev_cp == -1) {
 
-     			if (cc == 0) {
 
-     				prev_cp = cp;
 
-     			} else {
 
-     				ret.push(cp);
 
-     			}
 
-     		} else if (prev_cc > 0 && prev_cc >= cc) {
 
-     			if (cc == 0) {
 
-     				ret.push(prev_cp, ...stack);
 
-     				stack.length = 0;
 
-     				prev_cp = cp;
 
-     			} else {
 
-     				stack.push(cp);
 
-     			}
 
-     			prev_cc = cc;
 
-     		} else {
 
-     			let composed = compose_pair(prev_cp, cp);
 
-     			if (composed >= 0) {
 
-     				prev_cp = composed;
 
-     			} else if (prev_cc == 0 && cc == 0) {
 
-     				ret.push(prev_cp);
 
-     				prev_cp = cp;
 
-     			} else {
 
-     				stack.push(cp);
 
-     				prev_cc = cc;
 
-     			}
 
-     		}
 
-     	}
 
-     	if (prev_cp >= 0) {
 
-     		ret.push(prev_cp, ...stack);	
 
-     	}
 
-     	return ret;
 
-     }
 
-     // note: cps can be iterable
 
-     function nfd(cps) {
 
-     	return decomposed(cps).map(unpack_cp);
 
-     }
 
-     function nfc(cps) {
 
-     	return composed_from_decomposed(decomposed(cps));
 
-     }
 
-     const HYPHEN = 0x2D;
 
-     const STOP_CH = '.';
 
-     const FE0F = 0xFE0F;
 
-     const UNIQUE_PH = 1;
 
-     // 20230913: replace [...v] with Array_from(v) to avoid large spreads
 
-     const Array_from = x => Array.from(x); // Array.from.bind(Array);
 
-     function group_has_cp(g, cp) {
 
-     	// 20230913: keep primary and secondary distinct instead of creating valid union
 
-     	return g.P.has(cp) || g.Q.has(cp);
 
-     }
 
-     class Emoji extends Array {
 
-     	get is_emoji() { return true; } // free tagging system
 
-     }
 
-     let MAPPED, IGNORED, CM, NSM, ESCAPE, GROUPS, WHOLE_VALID, WHOLE_MAP, VALID, EMOJI_LIST, EMOJI_ROOT;
 
-     function init() {
 
-     	if (MAPPED) return;
 
-     	
 
-     	let r = read_compressed_payload(COMPRESSED$1);
 
-     	const read_sorted_array = () => read_sorted(r);
 
-     	const read_sorted_set = () => new Set(read_sorted_array());
 
-     	const set_add_many = (set, v) => v.forEach(x => set.add(x));
 
-     	MAPPED = new Map(read_mapped(r)); 
 
-     	IGNORED = read_sorted_set(); // ignored characters are not valid, so just read raw codepoints
 
-     	/*
 
-     	// direct include from payload is smaller than the decompression code
 
-     	const FENCED = new Map(read_array_while(() => {
 
-     		let cp = r();
 
-     		if (cp) return [cp, read_str(r())];
 
-     	}));
 
-     	*/
 
-     	// 20230217: we still need all CM for proper error formatting
 
-     	// but norm only needs NSM subset that are potentially-valid
 
-     	CM = read_sorted_array();
 
-     	NSM = new Set(read_sorted_array().map(i => CM[i]));
 
-     	CM = new Set(CM);
 
-     	
 
-     	ESCAPE = read_sorted_set(); // characters that should not be printed
 
-     	read_sorted_set(); // only needed to illustrate ens_tokenize() transformations
 
-     	let chunks = read_sorted_arrays(r);
 
-     	let unrestricted = r();
 
-     	//const read_chunked = () => new Set(read_sorted_array().flatMap(i => chunks[i]).concat(read_sorted_array()));
 
-     	const read_chunked = () => {
 
-     		// 20230921: build set in parts, 2x faster
 
-     		let set = new Set();
 
-     		read_sorted_array().forEach(i => set_add_many(set, chunks[i]));
 
-     		set_add_many(set, read_sorted_array());
 
-     		return set; 
 
-     	};
 
-     	GROUPS = read_array_while(i => {
 
-     		// minifier property mangling seems unsafe
 
-     		// so these are manually renamed to single chars
 
-     		let N = read_array_while(r).map(x => x+0x60);
 
-     		if (N.length) {
 
-     			let R = i >= unrestricted; // unrestricted then restricted
 
-     			N[0] -= 32; // capitalize
 
-     			N = str_from_cps(N);
 
-     			if (R) N=`Restricted[${N}]`;
 
-     			let P = read_chunked(); // primary
 
-     			let Q = read_chunked(); // secondary
 
-     			let M = !r(); // not-whitelisted, check for NSM
 
-     			// *** this code currently isn't needed ***
 
-     			/*
 
-     			let V = [...P, ...Q].sort((a, b) => a-b); // derive: sorted valid
 
-     			let M = r()-1; // number of combining mark
 
-     			if (M < 0) { // whitelisted
 
-     				M = new Map(read_array_while(() => {
 
-     					let i = r();
 
-     					if (i) return [V[i-1], read_array_while(() => {
 
-     						let v = read_array_while(r);
 
-     						if (v.length) return v.map(x => x-1);
 
-     					})];
 
-     				}));
 
-     			}*/
 
-     			return {N, P, Q, M, R};
 
-     		}
 
-     	});
 
-     	// decode compressed wholes
 
-     	WHOLE_VALID = read_sorted_set();
 
-     	WHOLE_MAP = new Map();
 
-     	let wholes = read_sorted_array().concat(Array_from(WHOLE_VALID)).sort((a, b) => a-b); // must be sorted
 
-     	wholes.forEach((cp, i) => {
 
-     		let d = r(); 
 
-     		let w = wholes[i] = d ? wholes[i-d] : {V: [], M: new Map()};
 
-     		w.V.push(cp); // add to member set
 
-     		if (!WHOLE_VALID.has(cp)) {
 
-     			WHOLE_MAP.set(cp, w);  // register with whole map
 
-     		}
 
-     	});
 
-     	// compute confusable-extent complements
 
-     	// usage: WHOLE_MAP.get(cp).M.get(cp) = complement set
 
-     	for (let {V, M} of new Set(WHOLE_MAP.values())) {
 
-     		// connect all groups that have each whole character
 
-     		let recs = [];
 
-     		for (let cp of V) {
 
-     			let gs = GROUPS.filter(g => group_has_cp(g, cp));
 
-     			let rec = recs.find(({G}) => gs.some(g => G.has(g)));
 
-     			if (!rec) {
 
-     				rec = {G: new Set(), V: []};
 
-     				recs.push(rec);
 
-     			}
 
-     			rec.V.push(cp);
 
-     			set_add_many(rec.G, gs);
 
-     		}
 
-     		// per character cache groups which are not a member of the extent
 
-     		let union = recs.flatMap(x => Array_from(x.G)); // all of the groups used by this whole
 
-     		for (let {G, V} of recs) {
 
-     			let complement = new Set(union.filter(g => !G.has(g))); // groups not covered by the extent
 
-     			for (let cp of V) {
 
-     				M.set(cp, complement); // this is the same reference
 
-     			}
 
-     		}
 
-     	}
 
-     	// compute valid set
 
-     	// 20230924: VALID was union but can be re-used
 
-     	VALID = new Set(); // exists in 1+ groups
 
-     	let multi = new Set(); // exists in 2+ groups
 
-     	const add_to_union = cp => VALID.has(cp) ? multi.add(cp) : VALID.add(cp);
 
-     	for (let g of GROUPS) {
 
-     		for (let cp of g.P) add_to_union(cp);
 
-     		for (let cp of g.Q) add_to_union(cp);
 
-     	}
 
-     	// dual purpose WHOLE_MAP: return placeholder if unique non-confusable
 
-     	for (let cp of VALID) {
 
-     		if (!WHOLE_MAP.has(cp) && !multi.has(cp)) {
 
-     			WHOLE_MAP.set(cp, UNIQUE_PH);
 
-     		}
 
-     	}
 
-     	// add all decomposed parts
 
-     	// see derive: "Valid is Closed (via Brute-force)"
 
-     	set_add_many(VALID, nfd(VALID));
 
-     	
 
-     	// decode emoji
 
-     	// 20230719: emoji are now fully-expanded to avoid quirk logic 
 
-     	EMOJI_LIST = read_trie(r).map(v => Emoji.from(v)).sort(compare_arrays);
 
-     	EMOJI_ROOT = new Map(); // this has approx 7K nodes (2+ per emoji)
 
-     	for (let cps of EMOJI_LIST) {
 
-     		// 20230719: change to *slightly* stricter algorithm which disallows 
 
-     		// insertion of misplaced FE0F in emoji sequences (matching ENSIP-15)
 
-     		// example: beautified [A B] (eg. flag emoji) 
 
-     		//  before: allow: [A FE0F B], error: [A FE0F FE0F B] 
 
-     		//   after: error: both
 
-     		// note: this code now matches ENSNormalize.{cs,java} logic
 
-     		let prev = [EMOJI_ROOT];
 
-     		for (let cp of cps) {
 
-     			let next = prev.map(node => {
 
-     				let child = node.get(cp);
 
-     				if (!child) {
 
-     					// should this be object? 
 
-     					// (most have 1-2 items, few have many)
 
-     					// 20230719: no, v8 default map is 4?
 
-     					child = new Map();
 
-     					node.set(cp, child);
 
-     				}
 
-     				return child;
 
-     			});
 
-     			if (cp === FE0F) {
 
-     				prev.push(...next); // less than 20 elements
 
-     			} else {
 
-     				prev = next;
 
-     			}
 
-     		}
 
-     		for (let x of prev) {
 
-     			x.V = cps;
 
-     		}
 
-     	}
 
-     }
 
-     // if escaped: {HEX}
 
-     //       else: "x" {HEX}
 
-     function quoted_cp(cp) {
 
-     	return (should_escape(cp) ? '' : `${bidi_qq(safe_str_from_cps([cp]))} `) + quote_cp(cp);
 
-     }
 
-     // 20230211: some messages can be mixed-directional and result in spillover
 
-     // use 200E after a quoted string to force the remainder of a string from 
 
-     // acquring the direction of the quote
 
-     // https://www.w3.org/International/questions/qa-bidi-unicode-controls#exceptions
 
-     function bidi_qq(s) {
 
-     	return `"${s}"\u200E`; // strong LTR
 
-     }
 
-     function check_label_extension(cps) {
 
-     	if (cps.length >= 4 && cps[2] == HYPHEN && cps[3] == HYPHEN) {
 
-     		throw new Error(`invalid label extension: "${str_from_cps(cps.slice(0, 4))}"`); // this can only be ascii so cant be bidi
 
-     	}
 
-     }
 
-     function check_leading_underscore(cps) {
 
-     	const UNDERSCORE = 0x5F;
 
-     	for (let i = cps.lastIndexOf(UNDERSCORE); i > 0; ) {
 
-     		if (cps[--i] !== UNDERSCORE) {
 
-     			throw new Error('underscore allowed only at start');
 
-     		}
 
-     	}
 
-     }
 
-     // check that a fenced cp is not leading, trailing, or touching another fenced cp
 
-     function check_fenced(cps) {
 
-     	let cp = cps[0];
 
-     	let prev = FENCED.get(cp);
 
-     	if (prev) throw error_placement(`leading ${prev}`);
 
-     	let n = cps.length;
 
-     	let last = -1; // prevents trailing from throwing
 
-     	for (let i = 1; i < n; i++) {
 
-     		cp = cps[i];
 
-     		let match = FENCED.get(cp);
 
-     		if (match) {
 
-     			// since cps[0] isn't fenced, cps[1] cannot throw
 
-     			if (last == i) throw error_placement(`${prev} + ${match}`);
 
-     			last = i + 1;
 
-     			prev = match;
 
-     		}
 
-     	}
 
-     	if (last == n) throw error_placement(`trailing ${prev}`);
 
-     }
 
-     // create a safe to print string 
 
-     // invisibles are escaped
 
-     // leading cm uses placeholder
 
-     // if cps exceed max, middle truncate with ellipsis
 
-     // quoter(cp) => string, eg. 3000 => "{3000}"
 
-     // note: in html, you'd call this function then replace [<>&] with entities
 
-     function safe_str_from_cps(cps, max = Infinity, quoter = quote_cp) {
 
-     	//if (Number.isInteger(cps)) cps = [cps];
 
-     	//if (!Array.isArray(cps)) throw new TypeError(`expected codepoints`);
 
-     	let buf = [];
 
-     	if (is_combining_mark(cps[0])) buf.push('◌');
 
-     	if (cps.length > max) {
 
-     		max >>= 1;
 
-     		cps = [...cps.slice(0, max), 0x2026, ...cps.slice(-max)];
 
-     	}
 
-     	let prev = 0;
 
-     	let n = cps.length;
 
-     	for (let i = 0; i < n; i++) {
 
-     		let cp = cps[i];
 
-     		if (should_escape(cp)) {
 
-     			buf.push(str_from_cps(cps.slice(prev, i)));
 
-     			buf.push(quoter(cp));
 
-     			prev = i + 1;
 
-     		}
 
-     	}
 
-     	buf.push(str_from_cps(cps.slice(prev, n)));
 
-     	return buf.join('');
 
-     }
 
-     // note: set(s) cannot be exposed because they can be modified
 
-     // note: Object.freeze() doesn't work
 
-     function is_combining_mark(cp) {
 
-     	init();
 
-     	return CM.has(cp);
 
-     }
 
-     function should_escape(cp) {
 
-     	init();
 
-     	return ESCAPE.has(cp);
 
-     }
 
-     function ens_normalize(name) {
 
-     	return flatten(split(name, nfc, filter_fe0f));
 
-     }
 
-     function split(name, nf, ef) {
 
-     	if (!name) return []; // 20230719: empty name allowance
 
-     	init();
 
-     	let offset = 0;
 
-     	// https://unicode.org/reports/tr46/#Validity_Criteria
 
-     	// 4.) "The label must not contain a U+002E ( . ) FULL STOP."
 
-     	return name.split(STOP_CH).map(label => {
 
-     		let input = explode_cp(label);
 
-     		let info = {
 
-     			input,
 
-     			offset, // codepoint, not substring!
 
-     		};
 
-     		offset += input.length + 1; // + stop
 
-     		try {
 
-     			// 1.) "The label must be in Unicode Normalization Form NFC"
 
-     			let tokens = info.tokens = tokens_from_str(input, nf, ef);
 
-     			let token_count = tokens.length;
 
-     			let type;
 
-     			if (!token_count) { // the label was effectively empty (could of had ignored characters)
 
-     				//norm = [];
 
-     				//type = 'None'; // use this instead of next match, "ASCII"
 
-     				// 20230120: change to strict
 
-     				// https://discuss.ens.domains/t/ens-name-normalization-2nd/14564/59
 
-     				throw new Error(`empty label`);
 
-     			} 
 
-     			let norm = info.output = tokens.flat();
 
-     			check_leading_underscore(norm);
 
-     			let emoji = info.emoji = token_count > 1 || tokens[0].is_emoji; // same as: tokens.some(x => x.is_emoji);
 
-     			if (!emoji && norm.every(cp => cp < 0x80)) { // special case for ascii
 
-     				// 20230123: matches matches WHATWG, see note 3.3
 
-     				check_label_extension(norm); // only needed for ascii
 
-     				// cant have fenced
 
-     				// cant have cm
 
-     				// cant have wholes
 
-     				// see derive: "Fastpath ASCII"
 
-     				type = 'ASCII';
 
-     			} else {
 
-     				let chars = tokens.flatMap(x => x.is_emoji ? [] : x); // all of the nfc tokens concat together
 
-     				if (!chars.length) { // theres no text, just emoji
 
-     					type = 'Emoji';
 
-     				} else {
 
-     					// 5.) "The label must not begin with a combining mark, that is: General_Category=Mark."
 
-     					if (CM.has(norm[0])) throw error_placement('leading combining mark');
 
-     					for (let i = 1; i < token_count; i++) { // we've already checked the first token
 
-     						let cps = tokens[i];
 
-     						if (!cps.is_emoji && CM.has(cps[0])) { // every text token has emoji neighbors, eg. EtEEEtEt...
 
-     							// bidi_qq() not needed since emoji is LTR and cps is a CM
 
-     							throw error_placement(`emoji + combining mark: "${str_from_cps(tokens[i-1])} + ${safe_str_from_cps([cps[0]])}"`); 
 
-     						}
 
-     					}
 
-     					check_fenced(norm);
 
-     					let unique = Array_from(new Set(chars));
 
-     					let [g] = determine_group(unique); // take the first match
 
-     					// see derive: "Matching Groups have Same CM Style"
 
-     					// alternative: could form a hybrid type: Latin/Japanese/...	
 
-     					check_group(g, chars); // need text in order
 
-     					check_whole(g, unique); // only need unique text (order would be required for multiple-char confusables)
 
-     					type = g.N;
 
-     					// 20230121: consider exposing restricted flag
 
-     					// it's simpler to just check for 'Restricted'
 
-     					// or even better: type.endsWith(']')
 
-     					//if (g.R) info.restricted = true;
 
-     				}
 
-     			}
 
-     			info.type = type;
 
-     		} catch (err) {
 
-     			info.error = err; // use full error object
 
-     		}
 
-     		return info;
 
-     	});
 
-     }
 
-     function check_whole(group, unique) {
 
-     	let maker;
 
-     	let shared = [];
 
-     	for (let cp of unique) {
 
-     		let whole = WHOLE_MAP.get(cp);
 
-     		if (whole === UNIQUE_PH) return; // unique, non-confusable
 
-     		if (whole) {
 
-     			let set = whole.M.get(cp); // groups which have a character that look-like this character
 
-     			maker = maker ? maker.filter(g => set.has(g)) : Array_from(set);
 
-     			if (!maker.length) return; // confusable intersection is empty
 
-     		} else {
 
-     			shared.push(cp); 
 
-     		}
 
-     	}
 
-     	if (maker) {
 
-     		// we have 1+ confusable
 
-     		// check if any of the remaining groups
 
-     		// contain the shared characters too
 
-     		for (let g of maker) {
 
-     			if (shared.every(cp => group_has_cp(g, cp))) {
 
-     				throw new Error(`whole-script confusable: ${group.N}/${g.N}`);
 
-     			}
 
-     		}
 
-     	}
 
-     }
 
-     // assumption: unique.size > 0
 
-     // returns list of matching groups
 
-     function determine_group(unique) {
 
-     	let groups = GROUPS;
 
-     	for (let cp of unique) {
 
-     		// note: we need to dodge CM that are whitelisted
 
-     		// but that code isn't currently necessary
 
-     		let gs = groups.filter(g => group_has_cp(g, cp));
 
-     		if (!gs.length) {
 
-     			if (!GROUPS.some(g => group_has_cp(g, cp))) { 
 
-     				// the character was composed of valid parts
 
-     				// but it's NFC form is invalid
 
-     				// 20230716: change to more exact statement, see: ENSNormalize.{cs,java}
 
-     				// note: this doesn't have to be a composition
 
-     				// 20230720: change to full check
 
-     				throw error_disallowed(cp); // this should be rare
 
-     			} else {
 
-     				// there is no group that contains all these characters
 
-     				// throw using the highest priority group that matched
 
-     				// https://www.unicode.org/reports/tr39/#mixed_script_confusables
 
-     				throw error_group_member(groups[0], cp);
 
-     			}
 
-     		}
 
-     		groups = gs;
 
-     		if (gs.length == 1) break; // there is only one group left
 
-     	}
 
-     	// there are at least 1 group(s) with all of these characters
 
-     	return groups;
 
-     }
 
-     // throw on first error
 
-     function flatten(split) {
 
-     	return split.map(({input, error, output}) => {
 
-     		if (error) {
 
-     			// don't print label again if just a single label
 
-     			let msg = error.message;
 
-     			// bidi_qq() only necessary if msg is digits
 
-     			throw new Error(split.length == 1 ? msg : `Invalid label ${bidi_qq(safe_str_from_cps(input, 63))}: ${msg}`); 
 
-     		}
 
-     		return str_from_cps(output);
 
-     	}).join(STOP_CH);
 
-     }
 
-     function error_disallowed(cp) {
 
-     	// TODO: add cp to error?
 
-     	return new Error(`disallowed character: ${quoted_cp(cp)}`); 
 
-     }
 
-     function error_group_member(g, cp) {
 
-     	let quoted = quoted_cp(cp);
 
-     	let gg = GROUPS.find(g => g.P.has(cp)); // only check primary
 
-     	if (gg) {
 
-     		quoted = `${gg.N} ${quoted}`;
 
-     	}
 
-     	return new Error(`illegal mixture: ${g.N} + ${quoted}`);
 
-     }
 
-     function error_placement(where) {
 
-     	return new Error(`illegal placement: ${where}`);
 
-     }
 
-     // assumption: cps.length > 0
 
-     // assumption: cps[0] isn't a CM
 
-     // assumption: the previous character isn't an emoji
 
-     function check_group(g, cps) {
 
-     	for (let cp of cps) {
 
-     		if (!group_has_cp(g, cp)) {
 
-     			// for whitelisted scripts, this will throw illegal mixture on invalid cm, eg. "e{300}{300}"
 
-     			// at the moment, it's unnecessary to introduce an extra error type
 
-     			// until there exists a whitelisted multi-character
 
-     			//   eg. if (M < 0 && is_combining_mark(cp)) { ... }
 
-     			// there are 3 cases:
 
-     			//   1. illegal cm for wrong group => mixture error
 
-     			//   2. illegal cm for same group => cm error
 
-     			//       requires set of whitelist cm per group: 
 
-     			//        eg. new Set([...g.P, ...g.Q].flatMap(nfc).filter(cp => CM.has(cp)))
 
-     			//   3. wrong group => mixture error
 
-     			throw error_group_member(g, cp);
 
-     		}
 
-     	}
 
-     	//if (M >= 0) { // we have a known fixed cm count
 
-     	if (g.M) { // we need to check for NSM
 
-     		let decomposed = nfd(cps);
 
-     		for (let i = 1, e = decomposed.length; i < e; i++) { // see: assumption
 
-     			// 20230210: bugfix: using cps instead of decomposed h/t Carbon225
 
-     			/*
 
-     			if (CM.has(decomposed[i])) {
 
-     				let j = i + 1;
 
-     				while (j < e && CM.has(decomposed[j])) j++;
 
-     				if (j - i > M) {
 
-     					throw new Error(`too many combining marks: ${g.N} ${bidi_qq(str_from_cps(decomposed.slice(i-1, j)))} (${j-i}/${M})`);
 
-     				}
 
-     				i = j;
 
-     			}
 
-     			*/
 
-     			// 20230217: switch to NSM counting
 
-     			// https://www.unicode.org/reports/tr39/#Optional_Detection
 
-     			if (NSM.has(decomposed[i])) {
 
-     				let j = i + 1;
 
-     				for (let cp; j < e && NSM.has(cp = decomposed[j]); j++) {
 
-     					// a. Forbid sequences of the same nonspacing mark.
 
-     					for (let k = i; k < j; k++) { // O(n^2) but n < 100
 
-     						if (decomposed[k] == cp) {
 
-     							throw new Error(`duplicate non-spacing marks: ${quoted_cp(cp)}`);
 
-     						}
 
-     					}
 
-     				}
 
-     				// parse to end so we have full nsm count
 
-     				// b. Forbid sequences of more than 4 nonspacing marks (gc=Mn or gc=Me).
 
-     				if (j - i > NSM_MAX) {
 
-     					// note: this slice starts with a base char or spacing-mark cm
 
-     					throw new Error(`excessive non-spacing marks: ${bidi_qq(safe_str_from_cps(decomposed.slice(i-1, j)))} (${j-i}/${NSM_MAX})`);
 
-     				}
 
-     				i = j;
 
-     			}
 
-     		}
 
-     	}
 
-     	// *** this code currently isn't needed ***
 
-     	/*
 
-     	let cm_whitelist = M instanceof Map;
 
-     	for (let i = 0, e = cps.length; i < e; ) {
 
-     		let cp = cps[i++];
 
-     		let seqs = cm_whitelist && M.get(cp);
 
-     		if (seqs) { 
 
-     			// list of codepoints that can follow
 
-     			// if this exists, this will always be 1+
 
-     			let j = i;
 
-     			while (j < e && CM.has(cps[j])) j++;
 
-     			let cms = cps.slice(i, j);
 
-     			let match = seqs.find(seq => !compare_arrays(seq, cms));
 
-     			if (!match) throw new Error(`disallowed combining mark sequence: "${safe_str_from_cps([cp, ...cms])}"`);
 
-     			i = j;
 
-     		} else if (!V.has(cp)) {
 
-     			// https://www.unicode.org/reports/tr39/#mixed_script_confusables
 
-     			let quoted = quoted_cp(cp);
 
-     			for (let cp of cps) {
 
-     				let u = UNIQUE.get(cp);
 
-     				if (u && u !== g) {
 
-     					// if both scripts are restricted this error is confusing
 
-     					// because we don't differentiate RestrictedA from RestrictedB 
 
-     					if (!u.R) quoted = `${quoted} is ${u.N}`;
 
-     					break;
 
-     				}
 
-     			}
 
-     			throw new Error(`disallowed ${g.N} character: ${quoted}`);
 
-     			//throw new Error(`disallowed character: ${quoted} (expected ${g.N})`);
 
-     			//throw new Error(`${g.N} does not allow: ${quoted}`);
 
-     		}
 
-     	}
 
-     	if (!cm_whitelist) {
 
-     		let decomposed = nfd(cps);
 
-     		for (let i = 1, e = decomposed.length; i < e; i++) { // we know it can't be cm leading
 
-     			if (CM.has(decomposed[i])) {
 
-     				let j = i + 1;
 
-     				while (j < e && CM.has(decomposed[j])) j++;
 
-     				if (j - i > M) {
 
-     					throw new Error(`too many combining marks: "${str_from_cps(decomposed.slice(i-1, j))}" (${j-i}/${M})`);
 
-     				}
 
-     				i = j;
 
-     			}
 
-     		}
 
-     	}
 
-     	*/
 
-     }
 
-     // given a list of codepoints
 
-     // returns a list of lists, where emoji are a fully-qualified (as Array subclass)
 
-     // eg. explode_cp("abc💩d") => [[61, 62, 63], Emoji[1F4A9, FE0F], [64]]
 
-     // 20230818: rename for 'process' name collision h/t Javarome
 
-     // https://github.com/adraffy/ens-normalize.js/issues/23
 
-     function tokens_from_str(input, nf, ef) {
 
-     	let ret = [];
 
-     	let chars = [];
 
-     	input = input.slice().reverse(); // flip so we can pop
 
-     	while (input.length) {
 
-     		let emoji = consume_emoji_reversed(input);
 
-     		if (emoji) {
 
-     			if (chars.length) {
 
-     				ret.push(nf(chars));
 
-     				chars = [];
 
-     			}
 
-     			ret.push(ef(emoji));
 
-     		} else {
 
-     			let cp = input.pop();
 
-     			if (VALID.has(cp)) {
 
-     				chars.push(cp);
 
-     			} else {
 
-     				let cps = MAPPED.get(cp);
 
-     				if (cps) {
 
-     					chars.push(...cps); // less than 10 elements
 
-     				} else if (!IGNORED.has(cp)) {
 
-     					// 20230912: unicode 15.1 changed the order of processing such that
 
-     					// disallowed parts are only rejected after NFC
 
-     					// https://unicode.org/reports/tr46/#Validity_Criteria
 
-     					// this doesn't impact normalization as of today
 
-     					// technically, this error can be removed as the group logic will apply similar logic
 
-     					// however the error type might be less clear
 
-     					throw error_disallowed(cp);
 
-     				}
 
-     			}
 
-     		}
 
-     	}
 
-     	if (chars.length) {
 
-     		ret.push(nf(chars));
 
-     	}
 
-     	return ret;
 
-     }
 
-     function filter_fe0f(cps) {
 
-     	return cps.filter(cp => cp != FE0F);
 
-     }
 
-     // given array of codepoints
 
-     // returns the longest valid emoji sequence (or undefined if no match)
 
-     // *MUTATES* the supplied array
 
-     // disallows interleaved ignored characters
 
-     // fills (optional) eaten array with matched codepoints
 
-     function consume_emoji_reversed(cps, eaten) {
 
-     	let node = EMOJI_ROOT;
 
-     	let emoji;
 
-     	let pos = cps.length;
 
-     	while (pos) {
 
-     		node = node.get(cps[--pos]);
 
-     		if (!node) break;
 
-     		let {V} = node;
 
-     		if (V) { // this is a valid emoji (so far)
 
-     			emoji = V;
 
-     			cps.length = pos; // truncate
 
-     		}
 
-     	}
 
-     	return emoji;
 
-     }
 
-     const Zeros = new Uint8Array(32);
 
-     Zeros.fill(0);
 
-     function checkComponent(comp) {
 
-         assertArgument(comp.length !== 0, "invalid ENS name; empty component", "comp", comp);
 
-         return comp;
 
-     }
 
-     function ensNameSplit(name) {
 
-         const bytes = toUtf8Bytes(ensNormalize(name));
 
-         const comps = [];
 
-         if (name.length === 0) {
 
-             return comps;
 
-         }
 
-         let last = 0;
 
-         for (let i = 0; i < bytes.length; i++) {
 
-             const d = bytes[i];
 
-             // A separator (i.e. "."); copy this component
 
-             if (d === 0x2e) {
 
-                 comps.push(checkComponent(bytes.slice(last, i)));
 
-                 last = i + 1;
 
-             }
 
-         }
 
-         // There was a stray separator at the end of the name
 
-         assertArgument(last < bytes.length, "invalid ENS name; empty component", "name", name);
 
-         comps.push(checkComponent(bytes.slice(last)));
 
-         return comps;
 
-     }
 
-     /**
 
-      *  Returns the ENS %%name%% normalized.
 
-      */
 
-     function ensNormalize(name) {
 
-         try {
 
-             if (name.length === 0) {
 
-                 throw new Error("empty label");
 
-             }
 
-             return ens_normalize(name);
 
-         }
 
-         catch (error) {
 
-             assertArgument(false, `invalid ENS name (${error.message})`, "name", name);
 
-         }
 
-     }
 
-     /**
 
-      *  Returns ``true`` if %%name%% is a valid ENS name.
 
-      */
 
-     function isValidName(name) {
 
-         try {
 
-             return (ensNameSplit(name).length !== 0);
 
-         }
 
-         catch (error) { }
 
-         return false;
 
-     }
 
-     /**
 
-      *  Returns the [[link-namehash]] for %%name%%.
 
-      */
 
-     function namehash(name) {
 
-         assertArgument(typeof (name) === "string", "invalid ENS name; not a string", "name", name);
 
-         assertArgument(name.length, `invalid ENS name (empty label)`, "name", name);
 
-         let result = Zeros;
 
-         const comps = ensNameSplit(name);
 
-         while (comps.length) {
 
-             result = keccak256(concat([result, keccak256((comps.pop()))]));
 
-         }
 
-         return hexlify(result);
 
-     }
 
-     /**
 
-      *  Returns the DNS encoded %%name%%.
 
-      *
 
-      *  This is used for various parts of ENS name resolution, such
 
-      *  as the wildcard resolution.
 
-      */
 
-     function dnsEncode(name, _maxLength) {
 
-         const length = (_maxLength != null) ? _maxLength : 63;
 
-         assertArgument(length <= 255, "DNS encoded label cannot exceed 255", "length", length);
 
-         return hexlify(concat(ensNameSplit(name).map((comp) => {
 
-             assertArgument(comp.length <= length, `label ${JSON.stringify(name)} exceeds ${length} bytes`, "name", name);
 
-             const bytes = new Uint8Array(comp.length + 1);
 
-             bytes.set(comp, 1);
 
-             bytes[0] = bytes.length - 1;
 
-             return bytes;
 
-         }))) + "00";
 
-     }
 
-     function accessSetify(addr, storageKeys) {
 
-         return {
 
-             address: getAddress(addr),
 
-             storageKeys: storageKeys.map((storageKey, index) => {
 
-                 assertArgument(isHexString(storageKey, 32), "invalid slot", `storageKeys[${index}]`, storageKey);
 
-                 return storageKey.toLowerCase();
 
-             })
 
-         };
 
-     }
 
-     /**
 
-      *  Returns a [[AccessList]] from any ethers-supported access-list structure.
 
-      */
 
-     function accessListify(value) {
 
-         if (Array.isArray(value)) {
 
-             return value.map((set, index) => {
 
-                 if (Array.isArray(set)) {
 
-                     assertArgument(set.length === 2, "invalid slot set", `value[${index}]`, set);
 
-                     return accessSetify(set[0], set[1]);
 
-                 }
 
-                 assertArgument(set != null && typeof (set) === "object", "invalid address-slot set", "value", value);
 
-                 return accessSetify(set.address, set.storageKeys);
 
-             });
 
-         }
 
-         assertArgument(value != null && typeof (value) === "object", "invalid access list", "value", value);
 
-         const result = Object.keys(value).map((addr) => {
 
-             const storageKeys = value[addr].reduce((accum, storageKey) => {
 
-                 accum[storageKey] = true;
 
-                 return accum;
 
-             }, {});
 
-             return accessSetify(addr, Object.keys(storageKeys).sort());
 
-         });
 
-         result.sort((a, b) => (a.address.localeCompare(b.address)));
 
-         return result;
 
-     }
 
-     /**
 
-      *  Returns the address for the %%key%%.
 
-      *
 
-      *  The key may be any standard form of public key or a private key.
 
-      */
 
-     function computeAddress(key) {
 
-         let pubkey;
 
-         if (typeof (key) === "string") {
 
-             pubkey = SigningKey.computePublicKey(key, false);
 
-         }
 
-         else {
 
-             pubkey = key.publicKey;
 
-         }
 
-         return getAddress(keccak256("0x" + pubkey.substring(4)).substring(26));
 
-     }
 
-     /**
 
-      *  Returns the recovered address for the private key that was
 
-      *  used to sign %%digest%% that resulted in %%signature%%.
 
-      */
 
-     function recoverAddress(digest, signature) {
 
-         return computeAddress(SigningKey.recoverPublicKey(digest, signature));
 
-     }
 
-     const BN_0$4 = BigInt(0);
 
-     const BN_2$2 = BigInt(2);
 
-     const BN_27 = BigInt(27);
 
-     const BN_28 = BigInt(28);
 
-     const BN_35 = BigInt(35);
 
-     const BN_MAX_UINT = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
 
-     const BLOB_SIZE = 4096 * 32;
 
-     function getVersionedHash(version, hash) {
 
-         let versioned = version.toString(16);
 
-         while (versioned.length < 2) {
 
-             versioned = "0" + versioned;
 
-         }
 
-         versioned += sha256(hash).substring(4);
 
-         return "0x" + versioned;
 
-     }
 
-     function handleAddress(value) {
 
-         if (value === "0x") {
 
-             return null;
 
-         }
 
-         return getAddress(value);
 
-     }
 
-     function handleAccessList(value, param) {
 
-         try {
 
-             return accessListify(value);
 
-         }
 
-         catch (error) {
 
-             assertArgument(false, error.message, param, value);
 
-         }
 
-     }
 
-     function handleNumber(_value, param) {
 
-         if (_value === "0x") {
 
-             return 0;
 
-         }
 
-         return getNumber(_value, param);
 
-     }
 
-     function handleUint(_value, param) {
 
-         if (_value === "0x") {
 
-             return BN_0$4;
 
-         }
 
-         const value = getBigInt(_value, param);
 
-         assertArgument(value <= BN_MAX_UINT, "value exceeds uint size", param, value);
 
-         return value;
 
-     }
 
-     function formatNumber(_value, name) {
 
-         const value = getBigInt(_value, "value");
 
-         const result = toBeArray(value);
 
-         assertArgument(result.length <= 32, `value too large`, `tx.${name}`, value);
 
-         return result;
 
-     }
 
-     function formatAccessList(value) {
 
-         return accessListify(value).map((set) => [set.address, set.storageKeys]);
 
-     }
 
-     function formatHashes(value, param) {
 
-         assertArgument(Array.isArray(value), `invalid ${param}`, "value", value);
 
-         for (let i = 0; i < value.length; i++) {
 
-             assertArgument(isHexString(value[i], 32), "invalid ${ param } hash", `value[${i}]`, value[i]);
 
-         }
 
-         return value;
 
-     }
 
-     function _parseLegacy(data) {
 
-         const fields = decodeRlp(data);
 
-         assertArgument(Array.isArray(fields) && (fields.length === 9 || fields.length === 6), "invalid field count for legacy transaction", "data", data);
 
-         const tx = {
 
-             type: 0,
 
-             nonce: handleNumber(fields[0], "nonce"),
 
-             gasPrice: handleUint(fields[1], "gasPrice"),
 
-             gasLimit: handleUint(fields[2], "gasLimit"),
 
-             to: handleAddress(fields[3]),
 
-             value: handleUint(fields[4], "value"),
 
-             data: hexlify(fields[5]),
 
-             chainId: BN_0$4
 
-         };
 
-         // Legacy unsigned transaction
 
-         if (fields.length === 6) {
 
-             return tx;
 
-         }
 
-         const v = handleUint(fields[6], "v");
 
-         const r = handleUint(fields[7], "r");
 
-         const s = handleUint(fields[8], "s");
 
-         if (r === BN_0$4 && s === BN_0$4) {
 
-             // EIP-155 unsigned transaction
 
-             tx.chainId = v;
 
-         }
 
-         else {
 
-             // Compute the EIP-155 chain ID (or 0 for legacy)
 
-             let chainId = (v - BN_35) / BN_2$2;
 
-             if (chainId < BN_0$4) {
 
-                 chainId = BN_0$4;
 
-             }
 
-             tx.chainId = chainId;
 
-             // Signed Legacy Transaction
 
-             assertArgument(chainId !== BN_0$4 || (v === BN_27 || v === BN_28), "non-canonical legacy v", "v", fields[6]);
 
-             tx.signature = Signature.from({
 
-                 r: zeroPadValue(fields[7], 32),
 
-                 s: zeroPadValue(fields[8], 32),
 
-                 v
 
-             });
 
-             //tx.hash = keccak256(data);
 
-         }
 
-         return tx;
 
-     }
 
-     function _serializeLegacy(tx, sig) {
 
-         const fields = [
 
-             formatNumber(tx.nonce, "nonce"),
 
-             formatNumber(tx.gasPrice || 0, "gasPrice"),
 
-             formatNumber(tx.gasLimit, "gasLimit"),
 
-             (tx.to || "0x"),
 
-             formatNumber(tx.value, "value"),
 
-             tx.data,
 
-         ];
 
-         let chainId = BN_0$4;
 
-         if (tx.chainId != BN_0$4) {
 
-             // A chainId was provided; if non-zero we'll use EIP-155
 
-             chainId = getBigInt(tx.chainId, "tx.chainId");
 
-             // We have a chainId in the tx and an EIP-155 v in the signature,
 
-             // make sure they agree with each other
 
-             assertArgument(!sig || sig.networkV == null || sig.legacyChainId === chainId, "tx.chainId/sig.v mismatch", "sig", sig);
 
-         }
 
-         else if (tx.signature) {
 
-             // No explicit chainId, but EIP-155 have a derived implicit chainId
 
-             const legacy = tx.signature.legacyChainId;
 
-             if (legacy != null) {
 
-                 chainId = legacy;
 
-             }
 
-         }
 
-         // Requesting an unsigned transaction
 
-         if (!sig) {
 
-             // We have an EIP-155 transaction (chainId was specified and non-zero)
 
-             if (chainId !== BN_0$4) {
 
-                 fields.push(toBeArray(chainId));
 
-                 fields.push("0x");
 
-                 fields.push("0x");
 
-             }
 
-             return encodeRlp(fields);
 
-         }
 
-         // @TODO: We should probably check that tx.signature, chainId, and sig
 
-         //        match but that logic could break existing code, so schedule
 
-         //        this for the next major bump.
 
-         // Compute the EIP-155 v
 
-         let v = BigInt(27 + sig.yParity);
 
-         if (chainId !== BN_0$4) {
 
-             v = Signature.getChainIdV(chainId, sig.v);
 
-         }
 
-         else if (BigInt(sig.v) !== v) {
 
-             assertArgument(false, "tx.chainId/sig.v mismatch", "sig", sig);
 
-         }
 
-         // Add the signature
 
-         fields.push(toBeArray(v));
 
-         fields.push(toBeArray(sig.r));
 
-         fields.push(toBeArray(sig.s));
 
-         return encodeRlp(fields);
 
-     }
 
-     function _parseEipSignature(tx, fields) {
 
-         let yParity;
 
-         try {
 
-             yParity = handleNumber(fields[0], "yParity");
 
-             if (yParity !== 0 && yParity !== 1) {
 
-                 throw new Error("bad yParity");
 
-             }
 
-         }
 
-         catch (error) {
 
-             assertArgument(false, "invalid yParity", "yParity", fields[0]);
 
-         }
 
-         const r = zeroPadValue(fields[1], 32);
 
-         const s = zeroPadValue(fields[2], 32);
 
-         const signature = Signature.from({ r, s, yParity });
 
-         tx.signature = signature;
 
-     }
 
-     function _parseEip1559(data) {
 
-         const fields = decodeRlp(getBytes(data).slice(1));
 
-         assertArgument(Array.isArray(fields) && (fields.length === 9 || fields.length === 12), "invalid field count for transaction type: 2", "data", hexlify(data));
 
-         const tx = {
 
-             type: 2,
 
-             chainId: handleUint(fields[0], "chainId"),
 
-             nonce: handleNumber(fields[1], "nonce"),
 
-             maxPriorityFeePerGas: handleUint(fields[2], "maxPriorityFeePerGas"),
 
-             maxFeePerGas: handleUint(fields[3], "maxFeePerGas"),
 
-             gasPrice: null,
 
-             gasLimit: handleUint(fields[4], "gasLimit"),
 
-             to: handleAddress(fields[5]),
 
-             value: handleUint(fields[6], "value"),
 
-             data: hexlify(fields[7]),
 
-             accessList: handleAccessList(fields[8], "accessList"),
 
-         };
 
-         // Unsigned EIP-1559 Transaction
 
-         if (fields.length === 9) {
 
-             return tx;
 
-         }
 
-         //tx.hash = keccak256(data);
 
-         _parseEipSignature(tx, fields.slice(9));
 
-         return tx;
 
-     }
 
-     function _serializeEip1559(tx, sig) {
 
-         const fields = [
 
-             formatNumber(tx.chainId, "chainId"),
 
-             formatNumber(tx.nonce, "nonce"),
 
-             formatNumber(tx.maxPriorityFeePerGas || 0, "maxPriorityFeePerGas"),
 
-             formatNumber(tx.maxFeePerGas || 0, "maxFeePerGas"),
 
-             formatNumber(tx.gasLimit, "gasLimit"),
 
-             (tx.to || "0x"),
 
-             formatNumber(tx.value, "value"),
 
-             tx.data,
 
-             formatAccessList(tx.accessList || [])
 
-         ];
 
-         if (sig) {
 
-             fields.push(formatNumber(sig.yParity, "yParity"));
 
-             fields.push(toBeArray(sig.r));
 
-             fields.push(toBeArray(sig.s));
 
-         }
 
-         return concat(["0x02", encodeRlp(fields)]);
 
-     }
 
-     function _parseEip2930(data) {
 
-         const fields = decodeRlp(getBytes(data).slice(1));
 
-         assertArgument(Array.isArray(fields) && (fields.length === 8 || fields.length === 11), "invalid field count for transaction type: 1", "data", hexlify(data));
 
-         const tx = {
 
-             type: 1,
 
-             chainId: handleUint(fields[0], "chainId"),
 
-             nonce: handleNumber(fields[1], "nonce"),
 
-             gasPrice: handleUint(fields[2], "gasPrice"),
 
-             gasLimit: handleUint(fields[3], "gasLimit"),
 
-             to: handleAddress(fields[4]),
 
-             value: handleUint(fields[5], "value"),
 
-             data: hexlify(fields[6]),
 
-             accessList: handleAccessList(fields[7], "accessList")
 
-         };
 
-         // Unsigned EIP-2930 Transaction
 
-         if (fields.length === 8) {
 
-             return tx;
 
-         }
 
-         //tx.hash = keccak256(data);
 
-         _parseEipSignature(tx, fields.slice(8));
 
-         return tx;
 
-     }
 
-     function _serializeEip2930(tx, sig) {
 
-         const fields = [
 
-             formatNumber(tx.chainId, "chainId"),
 
-             formatNumber(tx.nonce, "nonce"),
 
-             formatNumber(tx.gasPrice || 0, "gasPrice"),
 
-             formatNumber(tx.gasLimit, "gasLimit"),
 
-             (tx.to || "0x"),
 
-             formatNumber(tx.value, "value"),
 
-             tx.data,
 
-             formatAccessList(tx.accessList || [])
 
-         ];
 
-         if (sig) {
 
-             fields.push(formatNumber(sig.yParity, "recoveryParam"));
 
-             fields.push(toBeArray(sig.r));
 
-             fields.push(toBeArray(sig.s));
 
-         }
 
-         return concat(["0x01", encodeRlp(fields)]);
 
-     }
 
-     function _parseEip4844(data) {
 
-         let fields = decodeRlp(getBytes(data).slice(1));
 
-         let typeName = "3";
 
-         let blobs = null;
 
-         // Parse the network format
 
-         if (fields.length === 4 && Array.isArray(fields[0])) {
 
-             typeName = "3 (network format)";
 
-             const fBlobs = fields[1], fCommits = fields[2], fProofs = fields[3];
 
-             assertArgument(Array.isArray(fBlobs), "invalid network format: blobs not an array", "fields[1]", fBlobs);
 
-             assertArgument(Array.isArray(fCommits), "invalid network format: commitments not an array", "fields[2]", fCommits);
 
-             assertArgument(Array.isArray(fProofs), "invalid network format: proofs not an array", "fields[3]", fProofs);
 
-             assertArgument(fBlobs.length === fCommits.length, "invalid network format: blobs/commitments length mismatch", "fields", fields);
 
-             assertArgument(fBlobs.length === fProofs.length, "invalid network format: blobs/proofs length mismatch", "fields", fields);
 
-             blobs = [];
 
-             for (let i = 0; i < fields[1].length; i++) {
 
-                 blobs.push({
 
-                     data: fBlobs[i],
 
-                     commitment: fCommits[i],
 
-                     proof: fProofs[i],
 
-                 });
 
-             }
 
-             fields = fields[0];
 
-         }
 
-         assertArgument(Array.isArray(fields) && (fields.length === 11 || fields.length === 14), `invalid field count for transaction type: ${typeName}`, "data", hexlify(data));
 
-         const tx = {
 
-             type: 3,
 
-             chainId: handleUint(fields[0], "chainId"),
 
-             nonce: handleNumber(fields[1], "nonce"),
 
-             maxPriorityFeePerGas: handleUint(fields[2], "maxPriorityFeePerGas"),
 
-             maxFeePerGas: handleUint(fields[3], "maxFeePerGas"),
 
-             gasPrice: null,
 
-             gasLimit: handleUint(fields[4], "gasLimit"),
 
-             to: handleAddress(fields[5]),
 
-             value: handleUint(fields[6], "value"),
 
-             data: hexlify(fields[7]),
 
-             accessList: handleAccessList(fields[8], "accessList"),
 
-             maxFeePerBlobGas: handleUint(fields[9], "maxFeePerBlobGas"),
 
-             blobVersionedHashes: fields[10]
 
-         };
 
-         if (blobs) {
 
-             tx.blobs = blobs;
 
-         }
 
-         assertArgument(tx.to != null, `invalid address for transaction type: ${typeName}`, "data", data);
 
-         assertArgument(Array.isArray(tx.blobVersionedHashes), "invalid blobVersionedHashes: must be an array", "data", data);
 
-         for (let i = 0; i < tx.blobVersionedHashes.length; i++) {
 
-             assertArgument(isHexString(tx.blobVersionedHashes[i], 32), `invalid blobVersionedHash at index ${i}: must be length 32`, "data", data);
 
-         }
 
-         // Unsigned EIP-4844 Transaction
 
-         if (fields.length === 11) {
 
-             return tx;
 
-         }
 
-         // @TODO: Do we need to do this? This is only called internally
 
-         // and used to verify hashes; it might save time to not do this
 
-         //tx.hash = keccak256(concat([ "0x03", encodeRlp(fields) ]));
 
-         _parseEipSignature(tx, fields.slice(11));
 
-         return tx;
 
-     }
 
-     function _serializeEip4844(tx, sig, blobs) {
 
-         const fields = [
 
-             formatNumber(tx.chainId, "chainId"),
 
-             formatNumber(tx.nonce, "nonce"),
 
-             formatNumber(tx.maxPriorityFeePerGas || 0, "maxPriorityFeePerGas"),
 
-             formatNumber(tx.maxFeePerGas || 0, "maxFeePerGas"),
 
-             formatNumber(tx.gasLimit, "gasLimit"),
 
-             (tx.to || ZeroAddress),
 
-             formatNumber(tx.value, "value"),
 
-             tx.data,
 
-             formatAccessList(tx.accessList || []),
 
-             formatNumber(tx.maxFeePerBlobGas || 0, "maxFeePerBlobGas"),
 
-             formatHashes(tx.blobVersionedHashes || [], "blobVersionedHashes")
 
-         ];
 
-         if (sig) {
 
-             fields.push(formatNumber(sig.yParity, "yParity"));
 
-             fields.push(toBeArray(sig.r));
 
-             fields.push(toBeArray(sig.s));
 
-             // We have blobs; return the network wrapped format
 
-             if (blobs) {
 
-                 return concat([
 
-                     "0x03",
 
-                     encodeRlp([
 
-                         fields,
 
-                         blobs.map((b) => b.data),
 
-                         blobs.map((b) => b.commitment),
 
-                         blobs.map((b) => b.proof),
 
-                     ])
 
-                 ]);
 
-             }
 
-         }
 
-         return concat(["0x03", encodeRlp(fields)]);
 
-     }
 
-     /**
 
-      *  A **Transaction** describes an operation to be executed on
 
-      *  Ethereum by an Externally Owned Account (EOA). It includes
 
-      *  who (the [[to]] address), what (the [[data]]) and how much (the
 
-      *  [[value]] in ether) the operation should entail.
 
-      *
 
-      *  @example:
 
-      *    tx = new Transaction()
 
-      *    //_result:
 
-      *
 
-      *    tx.data = "0x1234";
 
-      *    //_result:
 
-      */
 
-     class Transaction {
 
-         #type;
 
-         #to;
 
-         #data;
 
-         #nonce;
 
-         #gasLimit;
 
-         #gasPrice;
 
-         #maxPriorityFeePerGas;
 
-         #maxFeePerGas;
 
-         #value;
 
-         #chainId;
 
-         #sig;
 
-         #accessList;
 
-         #maxFeePerBlobGas;
 
-         #blobVersionedHashes;
 
-         #kzg;
 
-         #blobs;
 
-         /**
 
-          *  The transaction type.
 
-          *
 
-          *  If null, the type will be automatically inferred based on
 
-          *  explicit properties.
 
-          */
 
-         get type() { return this.#type; }
 
-         set type(value) {
 
-             switch (value) {
 
-                 case null:
 
-                     this.#type = null;
 
-                     break;
 
-                 case 0:
 
-                 case "legacy":
 
-                     this.#type = 0;
 
-                     break;
 
-                 case 1:
 
-                 case "berlin":
 
-                 case "eip-2930":
 
-                     this.#type = 1;
 
-                     break;
 
-                 case 2:
 
-                 case "london":
 
-                 case "eip-1559":
 
-                     this.#type = 2;
 
-                     break;
 
-                 case 3:
 
-                 case "cancun":
 
-                 case "eip-4844":
 
-                     this.#type = 3;
 
-                     break;
 
-                 default:
 
-                     assertArgument(false, "unsupported transaction type", "type", value);
 
-             }
 
-         }
 
-         /**
 
-          *  The name of the transaction type.
 
-          */
 
-         get typeName() {
 
-             switch (this.type) {
 
-                 case 0: return "legacy";
 
-                 case 1: return "eip-2930";
 
-                 case 2: return "eip-1559";
 
-                 case 3: return "eip-4844";
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  The ``to`` address for the transaction or ``null`` if the
 
-          *  transaction is an ``init`` transaction.
 
-          */
 
-         get to() {
 
-             const value = this.#to;
 
-             if (value == null && this.type === 3) {
 
-                 return ZeroAddress;
 
-             }
 
-             return value;
 
-         }
 
-         set to(value) {
 
-             this.#to = (value == null) ? null : getAddress(value);
 
-         }
 
-         /**
 
-          *  The transaction nonce.
 
-          */
 
-         get nonce() { return this.#nonce; }
 
-         set nonce(value) { this.#nonce = getNumber(value, "value"); }
 
-         /**
 
-          *  The gas limit.
 
-          */
 
-         get gasLimit() { return this.#gasLimit; }
 
-         set gasLimit(value) { this.#gasLimit = getBigInt(value); }
 
-         /**
 
-          *  The gas price.
 
-          *
 
-          *  On legacy networks this defines the fee that will be paid. On
 
-          *  EIP-1559 networks, this should be ``null``.
 
-          */
 
-         get gasPrice() {
 
-             const value = this.#gasPrice;
 
-             if (value == null && (this.type === 0 || this.type === 1)) {
 
-                 return BN_0$4;
 
-             }
 
-             return value;
 
-         }
 
-         set gasPrice(value) {
 
-             this.#gasPrice = (value == null) ? null : getBigInt(value, "gasPrice");
 
-         }
 
-         /**
 
-          *  The maximum priority fee per unit of gas to pay. On legacy
 
-          *  networks this should be ``null``.
 
-          */
 
-         get maxPriorityFeePerGas() {
 
-             const value = this.#maxPriorityFeePerGas;
 
-             if (value == null) {
 
-                 if (this.type === 2 || this.type === 3) {
 
-                     return BN_0$4;
 
-                 }
 
-                 return null;
 
-             }
 
-             return value;
 
-         }
 
-         set maxPriorityFeePerGas(value) {
 
-             this.#maxPriorityFeePerGas = (value == null) ? null : getBigInt(value, "maxPriorityFeePerGas");
 
-         }
 
-         /**
 
-          *  The maximum total fee per unit of gas to pay. On legacy
 
-          *  networks this should be ``null``.
 
-          */
 
-         get maxFeePerGas() {
 
-             const value = this.#maxFeePerGas;
 
-             if (value == null) {
 
-                 if (this.type === 2 || this.type === 3) {
 
-                     return BN_0$4;
 
-                 }
 
-                 return null;
 
-             }
 
-             return value;
 
-         }
 
-         set maxFeePerGas(value) {
 
-             this.#maxFeePerGas = (value == null) ? null : getBigInt(value, "maxFeePerGas");
 
-         }
 
-         /**
 
-          *  The transaction data. For ``init`` transactions this is the
 
-          *  deployment code.
 
-          */
 
-         get data() { return this.#data; }
 
-         set data(value) { this.#data = hexlify(value); }
 
-         /**
 
-          *  The amount of ether (in wei) to send in this transactions.
 
-          */
 
-         get value() { return this.#value; }
 
-         set value(value) {
 
-             this.#value = getBigInt(value, "value");
 
-         }
 
-         /**
 
-          *  The chain ID this transaction is valid on.
 
-          */
 
-         get chainId() { return this.#chainId; }
 
-         set chainId(value) { this.#chainId = getBigInt(value); }
 
-         /**
 
-          *  If signed, the signature for this transaction.
 
-          */
 
-         get signature() { return this.#sig || null; }
 
-         set signature(value) {
 
-             this.#sig = (value == null) ? null : Signature.from(value);
 
-         }
 
-         /**
 
-          *  The access list.
 
-          *
 
-          *  An access list permits discounted (but pre-paid) access to
 
-          *  bytecode and state variable access within contract execution.
 
-          */
 
-         get accessList() {
 
-             const value = this.#accessList || null;
 
-             if (value == null) {
 
-                 if (this.type === 1 || this.type === 2 || this.type === 3) {
 
-                     // @TODO: in v7, this should assign the value or become
 
-                     // a live object itself, otherwise mutation is inconsistent
 
-                     return [];
 
-                 }
 
-                 return null;
 
-             }
 
-             return value;
 
-         }
 
-         set accessList(value) {
 
-             this.#accessList = (value == null) ? null : accessListify(value);
 
-         }
 
-         /**
 
-          *  The max fee per blob gas for Cancun transactions.
 
-          */
 
-         get maxFeePerBlobGas() {
 
-             const value = this.#maxFeePerBlobGas;
 
-             if (value == null && this.type === 3) {
 
-                 return BN_0$4;
 
-             }
 
-             return value;
 
-         }
 
-         set maxFeePerBlobGas(value) {
 
-             this.#maxFeePerBlobGas = (value == null) ? null : getBigInt(value, "maxFeePerBlobGas");
 
-         }
 
-         /**
 
-          *  The BLOb versioned hashes for Cancun transactions.
 
-          */
 
-         get blobVersionedHashes() {
 
-             // @TODO: Mutation is inconsistent; if unset, the returned value
 
-             // cannot mutate the object, if set it can
 
-             let value = this.#blobVersionedHashes;
 
-             if (value == null && this.type === 3) {
 
-                 return [];
 
-             }
 
-             return value;
 
-         }
 
-         set blobVersionedHashes(value) {
 
-             if (value != null) {
 
-                 assertArgument(Array.isArray(value), "blobVersionedHashes must be an Array", "value", value);
 
-                 value = value.slice();
 
-                 for (let i = 0; i < value.length; i++) {
 
-                     assertArgument(isHexString(value[i], 32), "invalid blobVersionedHash", `value[${i}]`, value[i]);
 
-                 }
 
-             }
 
-             this.#blobVersionedHashes = value;
 
-         }
 
-         /**
 
-          *  The BLObs for the Transaction, if any.
 
-          *
 
-          *  If ``blobs`` is non-``null``, then the [[seriailized]]
 
-          *  will return the network formatted sidecar, otherwise it
 
-          *  will return the standard [[link-eip-2718]] payload. The
 
-          *  [[unsignedSerialized]] is unaffected regardless.
 
-          *
 
-          *  When setting ``blobs``, either fully valid [[Blob]] objects
 
-          *  may be specified (i.e. correctly padded, with correct
 
-          *  committments and proofs) or a raw [[BytesLike]] may
 
-          *  be provided.
 
-          *
 
-          *  If raw [[BytesLike]] are provided, the [[kzg]] property **must**
 
-          *  be already set. The blob will be correctly padded and the
 
-          *  [[KzgLibrary]] will be used to compute the committment and
 
-          *  proof for the blob.
 
-          *
 
-          *  A BLOb is a sequence of field elements, each of which must
 
-          *  be within the BLS field modulo, so some additional processing
 
-          *  may be required to encode arbitrary data to ensure each 32 byte
 
-          *  field is within the valid range.
 
-          *
 
-          *  Setting this automatically populates [[blobVersionedHashes]],
 
-          *  overwriting any existing values. Setting this to ``null``
 
-          *  does **not** remove the [[blobVersionedHashes]], leaving them
 
-          *  present.
 
-          */
 
-         get blobs() {
 
-             if (this.#blobs == null) {
 
-                 return null;
 
-             }
 
-             return this.#blobs.map((b) => Object.assign({}, b));
 
-         }
 
-         set blobs(_blobs) {
 
-             if (_blobs == null) {
 
-                 this.#blobs = null;
 
-                 return;
 
-             }
 
-             const blobs = [];
 
-             const versionedHashes = [];
 
-             for (let i = 0; i < _blobs.length; i++) {
 
-                 const blob = _blobs[i];
 
-                 if (isBytesLike(blob)) {
 
-                     assert(this.#kzg, "adding a raw blob requires a KZG library", "UNSUPPORTED_OPERATION", {
 
-                         operation: "set blobs()"
 
-                     });
 
-                     let data = getBytes(blob);
 
-                     assertArgument(data.length <= BLOB_SIZE, "blob is too large", `blobs[${i}]`, blob);
 
-                     // Pad blob if necessary
 
-                     if (data.length !== BLOB_SIZE) {
 
-                         const padded = new Uint8Array(BLOB_SIZE);
 
-                         padded.set(data);
 
-                         data = padded;
 
-                     }
 
-                     const commit = this.#kzg.blobToKzgCommitment(data);
 
-                     const proof = hexlify(this.#kzg.computeBlobKzgProof(data, commit));
 
-                     blobs.push({
 
-                         data: hexlify(data),
 
-                         commitment: hexlify(commit),
 
-                         proof
 
-                     });
 
-                     versionedHashes.push(getVersionedHash(1, commit));
 
-                 }
 
-                 else {
 
-                     const commit = hexlify(blob.commitment);
 
-                     blobs.push({
 
-                         data: hexlify(blob.data),
 
-                         commitment: commit,
 
-                         proof: hexlify(blob.proof)
 
-                     });
 
-                     versionedHashes.push(getVersionedHash(1, commit));
 
-                 }
 
-             }
 
-             this.#blobs = blobs;
 
-             this.#blobVersionedHashes = versionedHashes;
 
-         }
 
-         get kzg() { return this.#kzg; }
 
-         set kzg(kzg) {
 
-             this.#kzg = kzg;
 
-         }
 
-         /**
 
-          *  Creates a new Transaction with default values.
 
-          */
 
-         constructor() {
 
-             this.#type = null;
 
-             this.#to = null;
 
-             this.#nonce = 0;
 
-             this.#gasLimit = BN_0$4;
 
-             this.#gasPrice = null;
 
-             this.#maxPriorityFeePerGas = null;
 
-             this.#maxFeePerGas = null;
 
-             this.#data = "0x";
 
-             this.#value = BN_0$4;
 
-             this.#chainId = BN_0$4;
 
-             this.#sig = null;
 
-             this.#accessList = null;
 
-             this.#maxFeePerBlobGas = null;
 
-             this.#blobVersionedHashes = null;
 
-             this.#blobs = null;
 
-             this.#kzg = null;
 
-         }
 
-         /**
 
-          *  The transaction hash, if signed. Otherwise, ``null``.
 
-          */
 
-         get hash() {
 
-             if (this.signature == null) {
 
-                 return null;
 
-             }
 
-             return keccak256(this.#getSerialized(true, false));
 
-         }
 
-         /**
 
-          *  The pre-image hash of this transaction.
 
-          *
 
-          *  This is the digest that a [[Signer]] must sign to authorize
 
-          *  this transaction.
 
-          */
 
-         get unsignedHash() {
 
-             return keccak256(this.unsignedSerialized);
 
-         }
 
-         /**
 
-          *  The sending address, if signed. Otherwise, ``null``.
 
-          */
 
-         get from() {
 
-             if (this.signature == null) {
 
-                 return null;
 
-             }
 
-             return recoverAddress(this.unsignedHash, this.signature);
 
-         }
 
-         /**
 
-          *  The public key of the sender, if signed. Otherwise, ``null``.
 
-          */
 
-         get fromPublicKey() {
 
-             if (this.signature == null) {
 
-                 return null;
 
-             }
 
-             return SigningKey.recoverPublicKey(this.unsignedHash, this.signature);
 
-         }
 
-         /**
 
-          *  Returns true if signed.
 
-          *
 
-          *  This provides a Type Guard that properties requiring a signed
 
-          *  transaction are non-null.
 
-          */
 
-         isSigned() {
 
-             return this.signature != null;
 
-         }
 
-         #getSerialized(signed, sidecar) {
 
-             assert(!signed || this.signature != null, "cannot serialize unsigned transaction; maybe you meant .unsignedSerialized", "UNSUPPORTED_OPERATION", { operation: ".serialized" });
 
-             const sig = signed ? this.signature : null;
 
-             switch (this.inferType()) {
 
-                 case 0:
 
-                     return _serializeLegacy(this, sig);
 
-                 case 1:
 
-                     return _serializeEip2930(this, sig);
 
-                 case 2:
 
-                     return _serializeEip1559(this, sig);
 
-                 case 3:
 
-                     return _serializeEip4844(this, sig, sidecar ? this.blobs : null);
 
-             }
 
-             assert(false, "unsupported transaction type", "UNSUPPORTED_OPERATION", { operation: ".serialized" });
 
-         }
 
-         /**
 
-          *  The serialized transaction.
 
-          *
 
-          *  This throws if the transaction is unsigned. For the pre-image,
 
-          *  use [[unsignedSerialized]].
 
-          */
 
-         get serialized() {
 
-             return this.#getSerialized(true, true);
 
-         }
 
-         /**
 
-          *  The transaction pre-image.
 
-          *
 
-          *  The hash of this is the digest which needs to be signed to
 
-          *  authorize this transaction.
 
-          */
 
-         get unsignedSerialized() {
 
-             return this.#getSerialized(false, false);
 
-         }
 
-         /**
 
-          *  Return the most "likely" type; currently the highest
 
-          *  supported transaction type.
 
-          */
 
-         inferType() {
 
-             const types = this.inferTypes();
 
-             // Prefer London (EIP-1559) over Cancun (BLOb)
 
-             if (types.indexOf(2) >= 0) {
 
-                 return 2;
 
-             }
 
-             // Return the highest inferred type
 
-             return (types.pop());
 
-         }
 
-         /**
 
-          *  Validates the explicit properties and returns a list of compatible
 
-          *  transaction types.
 
-          */
 
-         inferTypes() {
 
-             // Checks that there are no conflicting properties set
 
-             const hasGasPrice = this.gasPrice != null;
 
-             const hasFee = (this.maxFeePerGas != null || this.maxPriorityFeePerGas != null);
 
-             const hasAccessList = (this.accessList != null);
 
-             const hasBlob = (this.#maxFeePerBlobGas != null || this.#blobVersionedHashes);
 
-             //if (hasGasPrice && hasFee) {
 
-             //    throw new Error("transaction cannot have gasPrice and maxFeePerGas");
 
-             //}
 
-             if (this.maxFeePerGas != null && this.maxPriorityFeePerGas != null) {
 
-                 assert(this.maxFeePerGas >= this.maxPriorityFeePerGas, "priorityFee cannot be more than maxFee", "BAD_DATA", { value: this });
 
-             }
 
-             //if (this.type === 2 && hasGasPrice) {
 
-             //    throw new Error("eip-1559 transaction cannot have gasPrice");
 
-             //}
 
-             assert(!hasFee || (this.type !== 0 && this.type !== 1), "transaction type cannot have maxFeePerGas or maxPriorityFeePerGas", "BAD_DATA", { value: this });
 
-             assert(this.type !== 0 || !hasAccessList, "legacy transaction cannot have accessList", "BAD_DATA", { value: this });
 
-             const types = [];
 
-             // Explicit type
 
-             if (this.type != null) {
 
-                 types.push(this.type);
 
-             }
 
-             else {
 
-                 if (hasFee) {
 
-                     types.push(2);
 
-                 }
 
-                 else if (hasGasPrice) {
 
-                     types.push(1);
 
-                     if (!hasAccessList) {
 
-                         types.push(0);
 
-                     }
 
-                 }
 
-                 else if (hasAccessList) {
 
-                     types.push(1);
 
-                     types.push(2);
 
-                 }
 
-                 else if (hasBlob && this.to) {
 
-                     types.push(3);
 
-                 }
 
-                 else {
 
-                     types.push(0);
 
-                     types.push(1);
 
-                     types.push(2);
 
-                     types.push(3);
 
-                 }
 
-             }
 
-             types.sort();
 
-             return types;
 
-         }
 
-         /**
 
-          *  Returns true if this transaction is a legacy transaction (i.e.
 
-          *  ``type === 0``).
 
-          *
 
-          *  This provides a Type Guard that the related properties are
 
-          *  non-null.
 
-          */
 
-         isLegacy() {
 
-             return (this.type === 0);
 
-         }
 
-         /**
 
-          *  Returns true if this transaction is berlin hardform transaction (i.e.
 
-          *  ``type === 1``).
 
-          *
 
-          *  This provides a Type Guard that the related properties are
 
-          *  non-null.
 
-          */
 
-         isBerlin() {
 
-             return (this.type === 1);
 
-         }
 
-         /**
 
-          *  Returns true if this transaction is london hardform transaction (i.e.
 
-          *  ``type === 2``).
 
-          *
 
-          *  This provides a Type Guard that the related properties are
 
-          *  non-null.
 
-          */
 
-         isLondon() {
 
-             return (this.type === 2);
 
-         }
 
-         /**
 
-          *  Returns true if this transaction is an [[link-eip-4844]] BLOB
 
-          *  transaction.
 
-          *
 
-          *  This provides a Type Guard that the related properties are
 
-          *  non-null.
 
-          */
 
-         isCancun() {
 
-             return (this.type === 3);
 
-         }
 
-         /**
 
-          *  Create a copy of this transaciton.
 
-          */
 
-         clone() {
 
-             return Transaction.from(this);
 
-         }
 
-         /**
 
-          *  Return a JSON-friendly object.
 
-          */
 
-         toJSON() {
 
-             const s = (v) => {
 
-                 if (v == null) {
 
-                     return null;
 
-                 }
 
-                 return v.toString();
 
-             };
 
-             return {
 
-                 type: this.type,
 
-                 to: this.to,
 
-                 //            from: this.from,
 
-                 data: this.data,
 
-                 nonce: this.nonce,
 
-                 gasLimit: s(this.gasLimit),
 
-                 gasPrice: s(this.gasPrice),
 
-                 maxPriorityFeePerGas: s(this.maxPriorityFeePerGas),
 
-                 maxFeePerGas: s(this.maxFeePerGas),
 
-                 value: s(this.value),
 
-                 chainId: s(this.chainId),
 
-                 sig: this.signature ? this.signature.toJSON() : null,
 
-                 accessList: this.accessList
 
-             };
 
-         }
 
-         /**
 
-          *  Create a **Transaction** from a serialized transaction or a
 
-          *  Transaction-like object.
 
-          */
 
-         static from(tx) {
 
-             if (tx == null) {
 
-                 return new Transaction();
 
-             }
 
-             if (typeof (tx) === "string") {
 
-                 const payload = getBytes(tx);
 
-                 if (payload[0] >= 0x7f) { // @TODO: > vs >= ??
 
-                     return Transaction.from(_parseLegacy(payload));
 
-                 }
 
-                 switch (payload[0]) {
 
-                     case 1: return Transaction.from(_parseEip2930(payload));
 
-                     case 2: return Transaction.from(_parseEip1559(payload));
 
-                     case 3: return Transaction.from(_parseEip4844(payload));
 
-                 }
 
-                 assert(false, "unsupported transaction type", "UNSUPPORTED_OPERATION", { operation: "from" });
 
-             }
 
-             const result = new Transaction();
 
-             if (tx.type != null) {
 
-                 result.type = tx.type;
 
-             }
 
-             if (tx.to != null) {
 
-                 result.to = tx.to;
 
-             }
 
-             if (tx.nonce != null) {
 
-                 result.nonce = tx.nonce;
 
-             }
 
-             if (tx.gasLimit != null) {
 
-                 result.gasLimit = tx.gasLimit;
 
-             }
 
-             if (tx.gasPrice != null) {
 
-                 result.gasPrice = tx.gasPrice;
 
-             }
 
-             if (tx.maxPriorityFeePerGas != null) {
 
-                 result.maxPriorityFeePerGas = tx.maxPriorityFeePerGas;
 
-             }
 
-             if (tx.maxFeePerGas != null) {
 
-                 result.maxFeePerGas = tx.maxFeePerGas;
 
-             }
 
-             if (tx.maxFeePerBlobGas != null) {
 
-                 result.maxFeePerBlobGas = tx.maxFeePerBlobGas;
 
-             }
 
-             if (tx.data != null) {
 
-                 result.data = tx.data;
 
-             }
 
-             if (tx.value != null) {
 
-                 result.value = tx.value;
 
-             }
 
-             if (tx.chainId != null) {
 
-                 result.chainId = tx.chainId;
 
-             }
 
-             if (tx.signature != null) {
 
-                 result.signature = Signature.from(tx.signature);
 
-             }
 
-             if (tx.accessList != null) {
 
-                 result.accessList = tx.accessList;
 
-             }
 
-             // This will get overwritten by blobs, if present
 
-             if (tx.blobVersionedHashes != null) {
 
-                 result.blobVersionedHashes = tx.blobVersionedHashes;
 
-             }
 
-             // Make sure we assign the kzg before assigning blobs, which
 
-             // require the library in the event raw blob data is provided.
 
-             if (tx.kzg != null) {
 
-                 result.kzg = tx.kzg;
 
-             }
 
-             if (tx.blobs != null) {
 
-                 result.blobs = tx.blobs;
 
-             }
 
-             if (tx.hash != null) {
 
-                 assertArgument(result.isSigned(), "unsigned transaction cannot define '.hash'", "tx", tx);
 
-                 assertArgument(result.hash === tx.hash, "hash mismatch", "tx", tx);
 
-             }
 
-             if (tx.from != null) {
 
-                 assertArgument(result.isSigned(), "unsigned transaction cannot define '.from'", "tx", tx);
 
-                 assertArgument(result.from.toLowerCase() === (tx.from || "").toLowerCase(), "from mismatch", "tx", tx);
 
-             }
 
-             return result;
 
-         }
 
-     }
 
-     /**
 
-      *  Computes the [[link-eip-191]] personal-sign message digest to sign.
 
-      *
 
-      *  This prefixes the message with [[MessagePrefix]] and the decimal length
 
-      *  of %%message%% and computes the [[keccak256]] digest.
 
-      *
 
-      *  If %%message%% is a string, it is converted to its UTF-8 bytes
 
-      *  first. To compute the digest of a [[DataHexString]], it must be converted
 
-      *  to [bytes](getBytes).
 
-      *
 
-      *  @example:
 
-      *    hashMessage("Hello World")
 
-      *    //_result:
 
-      *
 
-      *    // Hashes the SIX (6) string characters, i.e.
 
-      *    // [ "0", "x", "4", "2", "4", "3" ]
 
-      *    hashMessage("0x4243")
 
-      *    //_result:
 
-      *
 
-      *    // Hashes the TWO (2) bytes [ 0x42, 0x43 ]...
 
-      *    hashMessage(getBytes("0x4243"))
 
-      *    //_result:
 
-      *
 
-      *    // ...which is equal to using data
 
-      *    hashMessage(new Uint8Array([ 0x42, 0x43 ]))
 
-      *    //_result:
 
-      *
 
-      */
 
-     function hashMessage(message) {
 
-         if (typeof (message) === "string") {
 
-             message = toUtf8Bytes(message);
 
-         }
 
-         return keccak256(concat([
 
-             toUtf8Bytes(MessagePrefix),
 
-             toUtf8Bytes(String(message.length)),
 
-             message
 
-         ]));
 
-     }
 
-     /**
 
-      *  Return the address of the private key that produced
 
-      *  the signature %%sig%% during signing for %%message%%.
 
-      */
 
-     function verifyMessage(message, sig) {
 
-         const digest = hashMessage(message);
 
-         return recoverAddress(digest, sig);
 
-     }
 
-     const regexBytes = new RegExp("^bytes([0-9]+)$");
 
-     const regexNumber = new RegExp("^(u?int)([0-9]*)$");
 
-     const regexArray = new RegExp("^(.*)\\[([0-9]*)\\]$");
 
-     function _pack(type, value, isArray) {
 
-         switch (type) {
 
-             case "address":
 
-                 if (isArray) {
 
-                     return getBytes(zeroPadValue(value, 32));
 
-                 }
 
-                 return getBytes(getAddress(value));
 
-             case "string":
 
-                 return toUtf8Bytes(value);
 
-             case "bytes":
 
-                 return getBytes(value);
 
-             case "bool":
 
-                 value = (!!value ? "0x01" : "0x00");
 
-                 if (isArray) {
 
-                     return getBytes(zeroPadValue(value, 32));
 
-                 }
 
-                 return getBytes(value);
 
-         }
 
-         let match = type.match(regexNumber);
 
-         if (match) {
 
-             let signed = (match[1] === "int");
 
-             let size = parseInt(match[2] || "256");
 
-             assertArgument((!match[2] || match[2] === String(size)) && (size % 8 === 0) && size !== 0 && size <= 256, "invalid number type", "type", type);
 
-             if (isArray) {
 
-                 size = 256;
 
-             }
 
-             if (signed) {
 
-                 value = toTwos(value, size);
 
-             }
 
-             return getBytes(zeroPadValue(toBeArray(value), size / 8));
 
-         }
 
-         match = type.match(regexBytes);
 
-         if (match) {
 
-             const size = parseInt(match[1]);
 
-             assertArgument(String(size) === match[1] && size !== 0 && size <= 32, "invalid bytes type", "type", type);
 
-             assertArgument(dataLength(value) === size, `invalid value for ${type}`, "value", value);
 
-             if (isArray) {
 
-                 return getBytes(zeroPadBytes(value, 32));
 
-             }
 
-             return value;
 
-         }
 
-         match = type.match(regexArray);
 
-         if (match && Array.isArray(value)) {
 
-             const baseType = match[1];
 
-             const count = parseInt(match[2] || String(value.length));
 
-             assertArgument(count === value.length, `invalid array length for ${type}`, "value", value);
 
-             const result = [];
 
-             value.forEach(function (value) {
 
-                 result.push(_pack(baseType, value, true));
 
-             });
 
-             return getBytes(concat(result));
 
-         }
 
-         assertArgument(false, "invalid type", "type", type);
 
-     }
 
-     // @TODO: Array Enum
 
-     /**
 
-      *   Computes the [[link-solc-packed]] representation of %%values%%
 
-      *   respectively to their %%types%%.
 
-      *
 
-      *   @example:
 
-      *       addr = "0x8ba1f109551bd432803012645ac136ddd64dba72"
 
-      *       solidityPacked([ "address", "uint" ], [ addr, 45 ]);
 
-      *       //_result:
 
-      */
 
-     function solidityPacked(types, values) {
 
-         assertArgument(types.length === values.length, "wrong number of values; expected ${ types.length }", "values", values);
 
-         const tight = [];
 
-         types.forEach(function (type, index) {
 
-             tight.push(_pack(type, values[index]));
 
-         });
 
-         return hexlify(concat(tight));
 
-     }
 
-     /**
 
-      *   Computes the [[link-solc-packed]] [[keccak256]] hash of %%values%%
 
-      *   respectively to their %%types%%.
 
-      *
 
-      *   @example:
 
-      *       addr = "0x8ba1f109551bd432803012645ac136ddd64dba72"
 
-      *       solidityPackedKeccak256([ "address", "uint" ], [ addr, 45 ]);
 
-      *       //_result:
 
-      */
 
-     function solidityPackedKeccak256(types, values) {
 
-         return keccak256(solidityPacked(types, values));
 
-     }
 
-     /**
 
-      *   Computes the [[link-solc-packed]] [[sha256]] hash of %%values%%
 
-      *   respectively to their %%types%%.
 
-      *
 
-      *   @example:
 
-      *       addr = "0x8ba1f109551bd432803012645ac136ddd64dba72"
 
-      *       solidityPackedSha256([ "address", "uint" ], [ addr, 45 ]);
 
-      *       //_result:
 
-      */
 
-     function solidityPackedSha256(types, values) {
 
-         return sha256(solidityPacked(types, values));
 
-     }
 
-     //import { TypedDataDomain, TypedDataField } from "@ethersproject/providerabstract-signer";
 
-     const padding = new Uint8Array(32);
 
-     padding.fill(0);
 
-     const BN__1 = BigInt(-1);
 
-     const BN_0$3 = BigInt(0);
 
-     const BN_1$1 = BigInt(1);
 
-     const BN_MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
 
-     function hexPadRight(value) {
 
-         const bytes = getBytes(value);
 
-         const padOffset = bytes.length % 32;
 
-         if (padOffset) {
 
-             return concat([bytes, padding.slice(padOffset)]);
 
-         }
 
-         return hexlify(bytes);
 
-     }
 
-     const hexTrue = toBeHex(BN_1$1, 32);
 
-     const hexFalse = toBeHex(BN_0$3, 32);
 
-     const domainFieldTypes = {
 
-         name: "string",
 
-         version: "string",
 
-         chainId: "uint256",
 
-         verifyingContract: "address",
 
-         salt: "bytes32"
 
-     };
 
-     const domainFieldNames = [
 
-         "name", "version", "chainId", "verifyingContract", "salt"
 
-     ];
 
-     function checkString(key) {
 
-         return function (value) {
 
-             assertArgument(typeof (value) === "string", `invalid domain value for ${JSON.stringify(key)}`, `domain.${key}`, value);
 
-             return value;
 
-         };
 
-     }
 
-     const domainChecks = {
 
-         name: checkString("name"),
 
-         version: checkString("version"),
 
-         chainId: function (_value) {
 
-             const value = getBigInt(_value, "domain.chainId");
 
-             assertArgument(value >= 0, "invalid chain ID", "domain.chainId", _value);
 
-             if (Number.isSafeInteger(value)) {
 
-                 return Number(value);
 
-             }
 
-             return toQuantity(value);
 
-         },
 
-         verifyingContract: function (value) {
 
-             try {
 
-                 return getAddress(value).toLowerCase();
 
-             }
 
-             catch (error) { }
 
-             assertArgument(false, `invalid domain value "verifyingContract"`, "domain.verifyingContract", value);
 
-         },
 
-         salt: function (value) {
 
-             const bytes = getBytes(value, "domain.salt");
 
-             assertArgument(bytes.length === 32, `invalid domain value "salt"`, "domain.salt", value);
 
-             return hexlify(bytes);
 
-         }
 
-     };
 
-     function getBaseEncoder(type) {
 
-         // intXX and uintXX
 
-         {
 
-             const match = type.match(/^(u?)int(\d+)$/);
 
-             if (match) {
 
-                 const signed = (match[1] === "");
 
-                 const width = parseInt(match[2]);
 
-                 assertArgument(width % 8 === 0 && width !== 0 && width <= 256 && match[2] === String(width), "invalid numeric width", "type", type);
 
-                 const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1) : width);
 
-                 const boundsLower = signed ? ((boundsUpper + BN_1$1) * BN__1) : BN_0$3;
 
-                 return function (_value) {
 
-                     const value = getBigInt(_value, "value");
 
-                     assertArgument(value >= boundsLower && value <= boundsUpper, `value out-of-bounds for ${type}`, "value", value);
 
-                     return toBeHex(signed ? toTwos(value, 256) : value, 32);
 
-                 };
 
-             }
 
-         }
 
-         // bytesXX
 
-         {
 
-             const match = type.match(/^bytes(\d+)$/);
 
-             if (match) {
 
-                 const width = parseInt(match[1]);
 
-                 assertArgument(width !== 0 && width <= 32 && match[1] === String(width), "invalid bytes width", "type", type);
 
-                 return function (value) {
 
-                     const bytes = getBytes(value);
 
-                     assertArgument(bytes.length === width, `invalid length for ${type}`, "value", value);
 
-                     return hexPadRight(value);
 
-                 };
 
-             }
 
-         }
 
-         switch (type) {
 
-             case "address": return function (value) {
 
-                 return zeroPadValue(getAddress(value), 32);
 
-             };
 
-             case "bool": return function (value) {
 
-                 return ((!value) ? hexFalse : hexTrue);
 
-             };
 
-             case "bytes": return function (value) {
 
-                 return keccak256(value);
 
-             };
 
-             case "string": return function (value) {
 
-                 return id(value);
 
-             };
 
-         }
 
-         return null;
 
-     }
 
-     function encodeType(name, fields) {
 
-         return `${name}(${fields.map(({ name, type }) => (type + " " + name)).join(",")})`;
 
-     }
 
-     // foo[][3] => { base: "foo", index: "[][3]", array: {
 
-     //     base: "foo", prefix: "foo[]", count: 3 } }
 
-     function splitArray(type) {
 
-         const match = type.match(/^([^\x5b]*)((\x5b\d*\x5d)*)(\x5b(\d*)\x5d)$/);
 
-         if (match) {
 
-             return {
 
-                 base: match[1],
 
-                 index: (match[2] + match[4]),
 
-                 array: {
 
-                     base: match[1],
 
-                     prefix: (match[1] + match[2]),
 
-                     count: (match[5] ? parseInt(match[5]) : -1),
 
-                 }
 
-             };
 
-         }
 
-         return { base: type };
 
-     }
 
-     /**
 
-      *  A **TypedDataEncode** prepares and encodes [[link-eip-712]] payloads
 
-      *  for signed typed data.
 
-      *
 
-      *  This is useful for those that wish to compute various components of a
 
-      *  typed data hash, primary types, or sub-components, but generally the
 
-      *  higher level [[Signer-signTypedData]] is more useful.
 
-      */
 
-     class TypedDataEncoder {
 
-         /**
 
-          *  The primary type for the structured [[types]].
 
-          *
 
-          *  This is derived automatically from the [[types]], since no
 
-          *  recursion is possible, once the DAG for the types is consturcted
 
-          *  internally, the primary type must be the only remaining type with
 
-          *  no parent nodes.
 
-          */
 
-         primaryType;
 
-         #types;
 
-         /**
 
-          *  The types.
 
-          */
 
-         get types() {
 
-             return JSON.parse(this.#types);
 
-         }
 
-         #fullTypes;
 
-         #encoderCache;
 
-         /**
 
-          *  Create a new **TypedDataEncoder** for %%types%%.
 
-          *
 
-          *  This performs all necessary checking that types are valid and
 
-          *  do not violate the [[link-eip-712]] structural constraints as
 
-          *  well as computes the [[primaryType]].
 
-          */
 
-         constructor(_types) {
 
-             this.#fullTypes = new Map();
 
-             this.#encoderCache = new Map();
 
-             // Link struct types to their direct child structs
 
-             const links = new Map();
 
-             // Link structs to structs which contain them as a child
 
-             const parents = new Map();
 
-             // Link all subtypes within a given struct
 
-             const subtypes = new Map();
 
-             const types = {};
 
-             Object.keys(_types).forEach((type) => {
 
-                 types[type] = _types[type].map(({ name, type }) => {
 
-                     // Normalize the base type (unless name conflict)
 
-                     let { base, index } = splitArray(type);
 
-                     if (base === "int" && !_types["int"]) {
 
-                         base = "int256";
 
-                     }
 
-                     if (base === "uint" && !_types["uint"]) {
 
-                         base = "uint256";
 
-                     }
 
-                     return { name, type: (base + (index || "")) };
 
-                 });
 
-                 links.set(type, new Set());
 
-                 parents.set(type, []);
 
-                 subtypes.set(type, new Set());
 
-             });
 
-             this.#types = JSON.stringify(types);
 
-             for (const name in types) {
 
-                 const uniqueNames = new Set();
 
-                 for (const field of types[name]) {
 
-                     // Check each field has a unique name
 
-                     assertArgument(!uniqueNames.has(field.name), `duplicate variable name ${JSON.stringify(field.name)} in ${JSON.stringify(name)}`, "types", _types);
 
-                     uniqueNames.add(field.name);
 
-                     // Get the base type (drop any array specifiers)
 
-                     const baseType = splitArray(field.type).base;
 
-                     assertArgument(baseType !== name, `circular type reference to ${JSON.stringify(baseType)}`, "types", _types);
 
-                     // Is this a base encoding type?
 
-                     const encoder = getBaseEncoder(baseType);
 
-                     if (encoder) {
 
-                         continue;
 
-                     }
 
-                     assertArgument(parents.has(baseType), `unknown type ${JSON.stringify(baseType)}`, "types", _types);
 
-                     // Add linkage
 
-                     parents.get(baseType).push(name);
 
-                     links.get(name).add(baseType);
 
-                 }
 
-             }
 
-             // Deduce the primary type
 
-             const primaryTypes = Array.from(parents.keys()).filter((n) => (parents.get(n).length === 0));
 
-             assertArgument(primaryTypes.length !== 0, "missing primary type", "types", _types);
 
-             assertArgument(primaryTypes.length === 1, `ambiguous primary types or unused types: ${primaryTypes.map((t) => (JSON.stringify(t))).join(", ")}`, "types", _types);
 
-             defineProperties(this, { primaryType: primaryTypes[0] });
 
-             // Check for circular type references
 
-             function checkCircular(type, found) {
 
-                 assertArgument(!found.has(type), `circular type reference to ${JSON.stringify(type)}`, "types", _types);
 
-                 found.add(type);
 
-                 for (const child of links.get(type)) {
 
-                     if (!parents.has(child)) {
 
-                         continue;
 
-                     }
 
-                     // Recursively check children
 
-                     checkCircular(child, found);
 
-                     // Mark all ancestors as having this decendant
 
-                     for (const subtype of found) {
 
-                         subtypes.get(subtype).add(child);
 
-                     }
 
-                 }
 
-                 found.delete(type);
 
-             }
 
-             checkCircular(this.primaryType, new Set());
 
-             // Compute each fully describe type
 
-             for (const [name, set] of subtypes) {
 
-                 const st = Array.from(set);
 
-                 st.sort();
 
-                 this.#fullTypes.set(name, encodeType(name, types[name]) + st.map((t) => encodeType(t, types[t])).join(""));
 
-             }
 
-         }
 
-         /**
 
-          *  Returnthe encoder for the specific %%type%%.
 
-          */
 
-         getEncoder(type) {
 
-             let encoder = this.#encoderCache.get(type);
 
-             if (!encoder) {
 
-                 encoder = this.#getEncoder(type);
 
-                 this.#encoderCache.set(type, encoder);
 
-             }
 
-             return encoder;
 
-         }
 
-         #getEncoder(type) {
 
-             // Basic encoder type (address, bool, uint256, etc)
 
-             {
 
-                 const encoder = getBaseEncoder(type);
 
-                 if (encoder) {
 
-                     return encoder;
 
-                 }
 
-             }
 
-             // Array
 
-             const array = splitArray(type).array;
 
-             if (array) {
 
-                 const subtype = array.prefix;
 
-                 const subEncoder = this.getEncoder(subtype);
 
-                 return (value) => {
 
-                     assertArgument(array.count === -1 || array.count === value.length, `array length mismatch; expected length ${array.count}`, "value", value);
 
-                     let result = value.map(subEncoder);
 
-                     if (this.#fullTypes.has(subtype)) {
 
-                         result = result.map(keccak256);
 
-                     }
 
-                     return keccak256(concat(result));
 
-                 };
 
-             }
 
-             // Struct
 
-             const fields = this.types[type];
 
-             if (fields) {
 
-                 const encodedType = id(this.#fullTypes.get(type));
 
-                 return (value) => {
 
-                     const values = fields.map(({ name, type }) => {
 
-                         const result = this.getEncoder(type)(value[name]);
 
-                         if (this.#fullTypes.has(type)) {
 
-                             return keccak256(result);
 
-                         }
 
-                         return result;
 
-                     });
 
-                     values.unshift(encodedType);
 
-                     return concat(values);
 
-                 };
 
-             }
 
-             assertArgument(false, `unknown type: ${type}`, "type", type);
 
-         }
 
-         /**
 
-          *  Return the full type for %%name%%.
 
-          */
 
-         encodeType(name) {
 
-             const result = this.#fullTypes.get(name);
 
-             assertArgument(result, `unknown type: ${JSON.stringify(name)}`, "name", name);
 
-             return result;
 
-         }
 
-         /**
 
-          *  Return the encoded %%value%% for the %%type%%.
 
-          */
 
-         encodeData(type, value) {
 
-             return this.getEncoder(type)(value);
 
-         }
 
-         /**
 
-          *  Returns the hash of %%value%% for the type of %%name%%.
 
-          */
 
-         hashStruct(name, value) {
 
-             return keccak256(this.encodeData(name, value));
 
-         }
 
-         /**
 
-          *  Return the fulled encoded %%value%% for the [[types]].
 
-          */
 
-         encode(value) {
 
-             return this.encodeData(this.primaryType, value);
 
-         }
 
-         /**
 
-          *  Return the hash of the fully encoded %%value%% for the [[types]].
 
-          */
 
-         hash(value) {
 
-             return this.hashStruct(this.primaryType, value);
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         _visit(type, value, callback) {
 
-             // Basic encoder type (address, bool, uint256, etc)
 
-             {
 
-                 const encoder = getBaseEncoder(type);
 
-                 if (encoder) {
 
-                     return callback(type, value);
 
-                 }
 
-             }
 
-             // Array
 
-             const array = splitArray(type).array;
 
-             if (array) {
 
-                 assertArgument(array.count === -1 || array.count === value.length, `array length mismatch; expected length ${array.count}`, "value", value);
 
-                 return value.map((v) => this._visit(array.prefix, v, callback));
 
-             }
 
-             // Struct
 
-             const fields = this.types[type];
 
-             if (fields) {
 
-                 return fields.reduce((accum, { name, type }) => {
 
-                     accum[name] = this._visit(type, value[name], callback);
 
-                     return accum;
 
-                 }, {});
 
-             }
 
-             assertArgument(false, `unknown type: ${type}`, "type", type);
 
-         }
 
-         /**
 
-          *  Call %%calback%% for each value in %%value%%, passing the type and
 
-          *  component within %%value%%.
 
-          *
 
-          *  This is useful for replacing addresses or other transformation that
 
-          *  may be desired on each component, based on its type.
 
-          */
 
-         visit(value, callback) {
 
-             return this._visit(this.primaryType, value, callback);
 
-         }
 
-         /**
 
-          *  Create a new **TypedDataEncoder** for %%types%%.
 
-          */
 
-         static from(types) {
 
-             return new TypedDataEncoder(types);
 
-         }
 
-         /**
 
-          *  Return the primary type for %%types%%.
 
-          */
 
-         static getPrimaryType(types) {
 
-             return TypedDataEncoder.from(types).primaryType;
 
-         }
 
-         /**
 
-          *  Return the hashed struct for %%value%% using %%types%% and %%name%%.
 
-          */
 
-         static hashStruct(name, types, value) {
 
-             return TypedDataEncoder.from(types).hashStruct(name, value);
 
-         }
 
-         /**
 
-          *  Return the domain hash for %%domain%%.
 
-          */
 
-         static hashDomain(domain) {
 
-             const domainFields = [];
 
-             for (const name in domain) {
 
-                 if (domain[name] == null) {
 
-                     continue;
 
-                 }
 
-                 const type = domainFieldTypes[name];
 
-                 assertArgument(type, `invalid typed-data domain key: ${JSON.stringify(name)}`, "domain", domain);
 
-                 domainFields.push({ name, type });
 
-             }
 
-             domainFields.sort((a, b) => {
 
-                 return domainFieldNames.indexOf(a.name) - domainFieldNames.indexOf(b.name);
 
-             });
 
-             return TypedDataEncoder.hashStruct("EIP712Domain", { EIP712Domain: domainFields }, domain);
 
-         }
 
-         /**
 
-          *  Return the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
 
-          */
 
-         static encode(domain, types, value) {
 
-             return concat([
 
-                 "0x1901",
 
-                 TypedDataEncoder.hashDomain(domain),
 
-                 TypedDataEncoder.from(types).hash(value)
 
-             ]);
 
-         }
 
-         /**
 
-          *  Return the hash of the fully encoded [[link-eip-712]] %%value%% for %%types%% with %%domain%%.
 
-          */
 
-         static hash(domain, types, value) {
 
-             return keccak256(TypedDataEncoder.encode(domain, types, value));
 
-         }
 
-         // Replaces all address types with ENS names with their looked up address
 
-         /**
 
-          * Resolves to the value from resolving all addresses in %%value%% for
 
-          * %%types%% and the %%domain%%.
 
-          */
 
-         static async resolveNames(domain, types, value, resolveName) {
 
-             // Make a copy to isolate it from the object passed in
 
-             domain = Object.assign({}, domain);
 
-             // Allow passing null to ignore value
 
-             for (const key in domain) {
 
-                 if (domain[key] == null) {
 
-                     delete domain[key];
 
-                 }
 
-             }
 
-             // Look up all ENS names
 
-             const ensCache = {};
 
-             // Do we need to look up the domain's verifyingContract?
 
-             if (domain.verifyingContract && !isHexString(domain.verifyingContract, 20)) {
 
-                 ensCache[domain.verifyingContract] = "0x";
 
-             }
 
-             // We are going to use the encoder to visit all the base values
 
-             const encoder = TypedDataEncoder.from(types);
 
-             // Get a list of all the addresses
 
-             encoder.visit(value, (type, value) => {
 
-                 if (type === "address" && !isHexString(value, 20)) {
 
-                     ensCache[value] = "0x";
 
-                 }
 
-                 return value;
 
-             });
 
-             // Lookup each name
 
-             for (const name in ensCache) {
 
-                 ensCache[name] = await resolveName(name);
 
-             }
 
-             // Replace the domain verifyingContract if needed
 
-             if (domain.verifyingContract && ensCache[domain.verifyingContract]) {
 
-                 domain.verifyingContract = ensCache[domain.verifyingContract];
 
-             }
 
-             // Replace all ENS names with their address
 
-             value = encoder.visit(value, (type, value) => {
 
-                 if (type === "address" && ensCache[value]) {
 
-                     return ensCache[value];
 
-                 }
 
-                 return value;
 
-             });
 
-             return { domain, value };
 
-         }
 
-         /**
 
-          *  Returns the JSON-encoded payload expected by nodes which implement
 
-          *  the JSON-RPC [[link-eip-712]] method.
 
-          */
 
-         static getPayload(domain, types, value) {
 
-             // Validate the domain fields
 
-             TypedDataEncoder.hashDomain(domain);
 
-             // Derive the EIP712Domain Struct reference type
 
-             const domainValues = {};
 
-             const domainTypes = [];
 
-             domainFieldNames.forEach((name) => {
 
-                 const value = domain[name];
 
-                 if (value == null) {
 
-                     return;
 
-                 }
 
-                 domainValues[name] = domainChecks[name](value);
 
-                 domainTypes.push({ name, type: domainFieldTypes[name] });
 
-             });
 
-             const encoder = TypedDataEncoder.from(types);
 
-             // Get the normalized types
 
-             types = encoder.types;
 
-             const typesWithDomain = Object.assign({}, types);
 
-             assertArgument(typesWithDomain.EIP712Domain == null, "types must not contain EIP712Domain type", "types.EIP712Domain", types);
 
-             typesWithDomain.EIP712Domain = domainTypes;
 
-             // Validate the data structures and types
 
-             encoder.encode(value);
 
-             return {
 
-                 types: typesWithDomain,
 
-                 domain: domainValues,
 
-                 primaryType: encoder.primaryType,
 
-                 message: encoder.visit(value, (type, value) => {
 
-                     // bytes
 
-                     if (type.match(/^bytes(\d*)/)) {
 
-                         return hexlify(getBytes(value));
 
-                     }
 
-                     // uint or int
 
-                     if (type.match(/^u?int/)) {
 
-                         return getBigInt(value).toString();
 
-                     }
 
-                     switch (type) {
 
-                         case "address":
 
-                             return value.toLowerCase();
 
-                         case "bool":
 
-                             return !!value;
 
-                         case "string":
 
-                             assertArgument(typeof (value) === "string", "invalid string", "value", value);
 
-                             return value;
 
-                     }
 
-                     assertArgument(false, "unsupported type", "type", type);
 
-                 })
 
-             };
 
-         }
 
-     }
 
-     /**
 
-      *  Compute the address used to sign the typed data for the %%signature%%.
 
-      */
 
-     function verifyTypedData(domain, types, value, signature) {
 
-         return recoverAddress(TypedDataEncoder.hash(domain, types, value), signature);
 
-     }
 
-     /**
 
-      *  A fragment is a single item from an ABI, which may represent any of:
 
-      *
 
-      *  - [Functions](FunctionFragment)
 
-      *  - [Events](EventFragment)
 
-      *  - [Constructors](ConstructorFragment)
 
-      *  - Custom [Errors](ErrorFragment)
 
-      *  - [Fallback or Receive](FallbackFragment) functions
 
-      *
 
-      *  @_subsection api/abi/abi-coder:Fragments  [about-fragments]
 
-      */
 
-     // [ "a", "b" ] => { "a": 1, "b": 1 }
 
-     function setify(items) {
 
-         const result = new Set();
 
-         items.forEach((k) => result.add(k));
 
-         return Object.freeze(result);
 
-     }
 
-     const _kwVisibDeploy = "external public payable override";
 
-     const KwVisibDeploy = setify(_kwVisibDeploy.split(" "));
 
-     // Visibility Keywords
 
-     const _kwVisib = "constant external internal payable private public pure view override";
 
-     const KwVisib = setify(_kwVisib.split(" "));
 
-     const _kwTypes = "constructor error event fallback function receive struct";
 
-     const KwTypes = setify(_kwTypes.split(" "));
 
-     const _kwModifiers = "calldata memory storage payable indexed";
 
-     const KwModifiers = setify(_kwModifiers.split(" "));
 
-     const _kwOther = "tuple returns";
 
-     // All Keywords
 
-     const _keywords = [_kwTypes, _kwModifiers, _kwOther, _kwVisib].join(" ");
 
-     const Keywords = setify(_keywords.split(" "));
 
-     // Single character tokens
 
-     const SimpleTokens = {
 
-         "(": "OPEN_PAREN", ")": "CLOSE_PAREN",
 
-         "[": "OPEN_BRACKET", "]": "CLOSE_BRACKET",
 
-         ",": "COMMA", "@": "AT"
 
-     };
 
-     // Parser regexes to consume the next token
 
-     const regexWhitespacePrefix = new RegExp("^(\\s*)");
 
-     const regexNumberPrefix = new RegExp("^([0-9]+)");
 
-     const regexIdPrefix = new RegExp("^([a-zA-Z$_][a-zA-Z0-9$_]*)");
 
-     // Parser regexs to check validity
 
-     const regexId = new RegExp("^([a-zA-Z$_][a-zA-Z0-9$_]*)$");
 
-     const regexType = new RegExp("^(address|bool|bytes([0-9]*)|string|u?int([0-9]*))$");
 
-     class TokenString {
 
-         #offset;
 
-         #tokens;
 
-         get offset() { return this.#offset; }
 
-         get length() { return this.#tokens.length - this.#offset; }
 
-         constructor(tokens) {
 
-             this.#offset = 0;
 
-             this.#tokens = tokens.slice();
 
-         }
 
-         clone() { return new TokenString(this.#tokens); }
 
-         reset() { this.#offset = 0; }
 
-         #subTokenString(from = 0, to = 0) {
 
-             return new TokenString(this.#tokens.slice(from, to).map((t) => {
 
-                 return Object.freeze(Object.assign({}, t, {
 
-                     match: (t.match - from),
 
-                     linkBack: (t.linkBack - from),
 
-                     linkNext: (t.linkNext - from),
 
-                 }));
 
-             }));
 
-         }
 
-         // Pops and returns the value of the next token, if it is a keyword in allowed; throws if out of tokens
 
-         popKeyword(allowed) {
 
-             const top = this.peek();
 
-             if (top.type !== "KEYWORD" || !allowed.has(top.text)) {
 
-                 throw new Error(`expected keyword ${top.text}`);
 
-             }
 
-             return this.pop().text;
 
-         }
 
-         // Pops and returns the value of the next token if it is `type`; throws if out of tokens
 
-         popType(type) {
 
-             if (this.peek().type !== type) {
 
-                 const top = this.peek();
 
-                 throw new Error(`expected ${type}; got ${top.type} ${JSON.stringify(top.text)}`);
 
-             }
 
-             return this.pop().text;
 
-         }
 
-         // Pops and returns a "(" TOKENS ")"
 
-         popParen() {
 
-             const top = this.peek();
 
-             if (top.type !== "OPEN_PAREN") {
 
-                 throw new Error("bad start");
 
-             }
 
-             const result = this.#subTokenString(this.#offset + 1, top.match + 1);
 
-             this.#offset = top.match + 1;
 
-             return result;
 
-         }
 
-         // Pops and returns the items within "(" ITEM1 "," ITEM2 "," ... ")"
 
-         popParams() {
 
-             const top = this.peek();
 
-             if (top.type !== "OPEN_PAREN") {
 
-                 throw new Error("bad start");
 
-             }
 
-             const result = [];
 
-             while (this.#offset < top.match - 1) {
 
-                 const link = this.peek().linkNext;
 
-                 result.push(this.#subTokenString(this.#offset + 1, link));
 
-                 this.#offset = link;
 
-             }
 
-             this.#offset = top.match + 1;
 
-             return result;
 
-         }
 
-         // Returns the top Token, throwing if out of tokens
 
-         peek() {
 
-             if (this.#offset >= this.#tokens.length) {
 
-                 throw new Error("out-of-bounds");
 
-             }
 
-             return this.#tokens[this.#offset];
 
-         }
 
-         // Returns the next value, if it is a keyword in `allowed`
 
-         peekKeyword(allowed) {
 
-             const top = this.peekType("KEYWORD");
 
-             return (top != null && allowed.has(top)) ? top : null;
 
-         }
 
-         // Returns the value of the next token if it is `type`
 
-         peekType(type) {
 
-             if (this.length === 0) {
 
-                 return null;
 
-             }
 
-             const top = this.peek();
 
-             return (top.type === type) ? top.text : null;
 
-         }
 
-         // Returns the next token; throws if out of tokens
 
-         pop() {
 
-             const result = this.peek();
 
-             this.#offset++;
 
-             return result;
 
-         }
 
-         toString() {
 
-             const tokens = [];
 
-             for (let i = this.#offset; i < this.#tokens.length; i++) {
 
-                 const token = this.#tokens[i];
 
-                 tokens.push(`${token.type}:${token.text}`);
 
-             }
 
-             return `<TokenString ${tokens.join(" ")}>`;
 
-         }
 
-     }
 
-     function lex(text) {
 
-         const tokens = [];
 
-         const throwError = (message) => {
 
-             const token = (offset < text.length) ? JSON.stringify(text[offset]) : "$EOI";
 
-             throw new Error(`invalid token ${token} at ${offset}: ${message}`);
 
-         };
 
-         let brackets = [];
 
-         let commas = [];
 
-         let offset = 0;
 
-         while (offset < text.length) {
 
-             // Strip off any leading whitespace
 
-             let cur = text.substring(offset);
 
-             let match = cur.match(regexWhitespacePrefix);
 
-             if (match) {
 
-                 offset += match[1].length;
 
-                 cur = text.substring(offset);
 
-             }
 
-             const token = { depth: brackets.length, linkBack: -1, linkNext: -1, match: -1, type: "", text: "", offset, value: -1 };
 
-             tokens.push(token);
 
-             let type = (SimpleTokens[cur[0]] || "");
 
-             if (type) {
 
-                 token.type = type;
 
-                 token.text = cur[0];
 
-                 offset++;
 
-                 if (type === "OPEN_PAREN") {
 
-                     brackets.push(tokens.length - 1);
 
-                     commas.push(tokens.length - 1);
 
-                 }
 
-                 else if (type == "CLOSE_PAREN") {
 
-                     if (brackets.length === 0) {
 
-                         throwError("no matching open bracket");
 
-                     }
 
-                     token.match = brackets.pop();
 
-                     (tokens[token.match]).match = tokens.length - 1;
 
-                     token.depth--;
 
-                     token.linkBack = commas.pop();
 
-                     (tokens[token.linkBack]).linkNext = tokens.length - 1;
 
-                 }
 
-                 else if (type === "COMMA") {
 
-                     token.linkBack = commas.pop();
 
-                     (tokens[token.linkBack]).linkNext = tokens.length - 1;
 
-                     commas.push(tokens.length - 1);
 
-                 }
 
-                 else if (type === "OPEN_BRACKET") {
 
-                     token.type = "BRACKET";
 
-                 }
 
-                 else if (type === "CLOSE_BRACKET") {
 
-                     // Remove the CLOSE_BRACKET
 
-                     let suffix = tokens.pop().text;
 
-                     if (tokens.length > 0 && tokens[tokens.length - 1].type === "NUMBER") {
 
-                         const value = tokens.pop().text;
 
-                         suffix = value + suffix;
 
-                         (tokens[tokens.length - 1]).value = getNumber(value);
 
-                     }
 
-                     if (tokens.length === 0 || tokens[tokens.length - 1].type !== "BRACKET") {
 
-                         throw new Error("missing opening bracket");
 
-                     }
 
-                     (tokens[tokens.length - 1]).text += suffix;
 
-                 }
 
-                 continue;
 
-             }
 
-             match = cur.match(regexIdPrefix);
 
-             if (match) {
 
-                 token.text = match[1];
 
-                 offset += token.text.length;
 
-                 if (Keywords.has(token.text)) {
 
-                     token.type = "KEYWORD";
 
-                     continue;
 
-                 }
 
-                 if (token.text.match(regexType)) {
 
-                     token.type = "TYPE";
 
-                     continue;
 
-                 }
 
-                 token.type = "ID";
 
-                 continue;
 
-             }
 
-             match = cur.match(regexNumberPrefix);
 
-             if (match) {
 
-                 token.text = match[1];
 
-                 token.type = "NUMBER";
 
-                 offset += token.text.length;
 
-                 continue;
 
-             }
 
-             throw new Error(`unexpected token ${JSON.stringify(cur[0])} at position ${offset}`);
 
-         }
 
-         return new TokenString(tokens.map((t) => Object.freeze(t)));
 
-     }
 
-     // Check only one of `allowed` is in `set`
 
-     function allowSingle(set, allowed) {
 
-         let included = [];
 
-         for (const key in allowed.keys()) {
 
-             if (set.has(key)) {
 
-                 included.push(key);
 
-             }
 
-         }
 
-         if (included.length > 1) {
 
-             throw new Error(`conflicting types: ${included.join(", ")}`);
 
-         }
 
-     }
 
-     // Functions to process a Solidity Signature TokenString from left-to-right for...
 
-     // ...the name with an optional type, returning the name
 
-     function consumeName(type, tokens) {
 
-         if (tokens.peekKeyword(KwTypes)) {
 
-             const keyword = tokens.pop().text;
 
-             if (keyword !== type) {
 
-                 throw new Error(`expected ${type}, got ${keyword}`);
 
-             }
 
-         }
 
-         return tokens.popType("ID");
 
-     }
 
-     // ...all keywords matching allowed, returning the keywords
 
-     function consumeKeywords(tokens, allowed) {
 
-         const keywords = new Set();
 
-         while (true) {
 
-             const keyword = tokens.peekType("KEYWORD");
 
-             if (keyword == null || (allowed && !allowed.has(keyword))) {
 
-                 break;
 
-             }
 
-             tokens.pop();
 
-             if (keywords.has(keyword)) {
 
-                 throw new Error(`duplicate keywords: ${JSON.stringify(keyword)}`);
 
-             }
 
-             keywords.add(keyword);
 
-         }
 
-         return Object.freeze(keywords);
 
-     }
 
-     // ...all visibility keywords, returning the coalesced mutability
 
-     function consumeMutability(tokens) {
 
-         let modifiers = consumeKeywords(tokens, KwVisib);
 
-         // Detect conflicting modifiers
 
-         allowSingle(modifiers, setify("constant payable nonpayable".split(" ")));
 
-         allowSingle(modifiers, setify("pure view payable nonpayable".split(" ")));
 
-         // Process mutability states
 
-         if (modifiers.has("view")) {
 
-             return "view";
 
-         }
 
-         if (modifiers.has("pure")) {
 
-             return "pure";
 
-         }
 
-         if (modifiers.has("payable")) {
 
-             return "payable";
 
-         }
 
-         if (modifiers.has("nonpayable")) {
 
-             return "nonpayable";
 
-         }
 
-         // Process legacy `constant` last
 
-         if (modifiers.has("constant")) {
 
-             return "view";
 
-         }
 
-         return "nonpayable";
 
-     }
 
-     // ...a parameter list, returning the ParamType list
 
-     function consumeParams(tokens, allowIndexed) {
 
-         return tokens.popParams().map((t) => ParamType.from(t, allowIndexed));
 
-     }
 
-     // ...a gas limit, returning a BigNumber or null if none
 
-     function consumeGas(tokens) {
 
-         if (tokens.peekType("AT")) {
 
-             tokens.pop();
 
-             if (tokens.peekType("NUMBER")) {
 
-                 return getBigInt(tokens.pop().text);
 
-             }
 
-             throw new Error("invalid gas");
 
-         }
 
-         return null;
 
-     }
 
-     function consumeEoi(tokens) {
 
-         if (tokens.length) {
 
-             throw new Error(`unexpected tokens at offset ${tokens.offset}: ${tokens.toString()}`);
 
-         }
 
-     }
 
-     const regexArrayType = new RegExp(/^(.*)\[([0-9]*)\]$/);
 
-     function verifyBasicType(type) {
 
-         const match = type.match(regexType);
 
-         assertArgument(match, "invalid type", "type", type);
 
-         if (type === "uint") {
 
-             return "uint256";
 
-         }
 
-         if (type === "int") {
 
-             return "int256";
 
-         }
 
-         if (match[2]) {
 
-             // bytesXX
 
-             const length = parseInt(match[2]);
 
-             assertArgument(length !== 0 && length <= 32, "invalid bytes length", "type", type);
 
-         }
 
-         else if (match[3]) {
 
-             // intXX or uintXX
 
-             const size = parseInt(match[3]);
 
-             assertArgument(size !== 0 && size <= 256 && (size % 8) === 0, "invalid numeric width", "type", type);
 
-         }
 
-         return type;
 
-     }
 
-     // Make the Fragment constructors effectively private
 
-     const _guard$2 = {};
 
-     const internal$1 = Symbol.for("_ethers_internal");
 
-     const ParamTypeInternal = "_ParamTypeInternal";
 
-     const ErrorFragmentInternal = "_ErrorInternal";
 
-     const EventFragmentInternal = "_EventInternal";
 
-     const ConstructorFragmentInternal = "_ConstructorInternal";
 
-     const FallbackFragmentInternal = "_FallbackInternal";
 
-     const FunctionFragmentInternal = "_FunctionInternal";
 
-     const StructFragmentInternal = "_StructInternal";
 
-     /**
 
-      *  Each input and output of a [[Fragment]] is an Array of **ParamType**.
 
-      */
 
-     class ParamType {
 
-         /**
 
-          *  The local name of the parameter (or ``""`` if unbound)
 
-          */
 
-         name;
 
-         /**
 
-          *  The fully qualified type (e.g. ``"address"``, ``"tuple(address)"``,
 
-          *  ``"uint256[3][]"``)
 
-          */
 
-         type;
 
-         /**
 
-          *  The base type (e.g. ``"address"``, ``"tuple"``, ``"array"``)
 
-          */
 
-         baseType;
 
-         /**
 
-          *  True if the parameters is indexed.
 
-          *
 
-          *  For non-indexable types this is ``null``.
 
-          */
 
-         indexed;
 
-         /**
 
-          *  The components for the tuple.
 
-          *
 
-          *  For non-tuple types this is ``null``.
 
-          */
 
-         components;
 
-         /**
 
-          *  The array length, or ``-1`` for dynamic-lengthed arrays.
 
-          *
 
-          *  For non-array types this is ``null``.
 
-          */
 
-         arrayLength;
 
-         /**
 
-          *  The type of each child in the array.
 
-          *
 
-          *  For non-array types this is ``null``.
 
-          */
 
-         arrayChildren;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, name, type, baseType, indexed, components, arrayLength, arrayChildren) {
 
-             assertPrivate(guard, _guard$2, "ParamType");
 
-             Object.defineProperty(this, internal$1, { value: ParamTypeInternal });
 
-             if (components) {
 
-                 components = Object.freeze(components.slice());
 
-             }
 
-             if (baseType === "array") {
 
-                 if (arrayLength == null || arrayChildren == null) {
 
-                     throw new Error("");
 
-                 }
 
-             }
 
-             else if (arrayLength != null || arrayChildren != null) {
 
-                 throw new Error("");
 
-             }
 
-             if (baseType === "tuple") {
 
-                 if (components == null) {
 
-                     throw new Error("");
 
-                 }
 
-             }
 
-             else if (components != null) {
 
-                 throw new Error("");
 
-             }
 
-             defineProperties(this, {
 
-                 name, type, baseType, indexed, components, arrayLength, arrayChildren
 
-             });
 
-         }
 
-         /**
 
-          *  Return a string representation of this type.
 
-          *
 
-          *  For example,
 
-          *
 
-          *  ``sighash" => "(uint256,address)"``
 
-          *
 
-          *  ``"minimal" => "tuple(uint256,address) indexed"``
 
-          *
 
-          *  ``"full" => "tuple(uint256 foo, address bar) indexed baz"``
 
-          */
 
-         format(format) {
 
-             if (format == null) {
 
-                 format = "sighash";
 
-             }
 
-             if (format === "json") {
 
-                 const name = this.name || "";
 
-                 if (this.isArray()) {
 
-                     const result = JSON.parse(this.arrayChildren.format("json"));
 
-                     result.name = name;
 
-                     result.type += `[${(this.arrayLength < 0 ? "" : String(this.arrayLength))}]`;
 
-                     return JSON.stringify(result);
 
-                 }
 
-                 const result = {
 
-                     type: ((this.baseType === "tuple") ? "tuple" : this.type),
 
-                     name
 
-                 };
 
-                 if (typeof (this.indexed) === "boolean") {
 
-                     result.indexed = this.indexed;
 
-                 }
 
-                 if (this.isTuple()) {
 
-                     result.components = this.components.map((c) => JSON.parse(c.format(format)));
 
-                 }
 
-                 return JSON.stringify(result);
 
-             }
 
-             let result = "";
 
-             // Array
 
-             if (this.isArray()) {
 
-                 result += this.arrayChildren.format(format);
 
-                 result += `[${(this.arrayLength < 0 ? "" : String(this.arrayLength))}]`;
 
-             }
 
-             else {
 
-                 if (this.isTuple()) {
 
-                     result += "(" + this.components.map((comp) => comp.format(format)).join((format === "full") ? ", " : ",") + ")";
 
-                 }
 
-                 else {
 
-                     result += this.type;
 
-                 }
 
-             }
 
-             if (format !== "sighash") {
 
-                 if (this.indexed === true) {
 
-                     result += " indexed";
 
-                 }
 
-                 if (format === "full" && this.name) {
 
-                     result += " " + this.name;
 
-                 }
 
-             }
 
-             return result;
 
-         }
 
-         /**
 
-          *  Returns true if %%this%% is an Array type.
 
-          *
 
-          *  This provides a type gaurd ensuring that [[arrayChildren]]
 
-          *  and [[arrayLength]] are non-null.
 
-          */
 
-         isArray() {
 
-             return (this.baseType === "array");
 
-         }
 
-         /**
 
-          *  Returns true if %%this%% is a Tuple type.
 
-          *
 
-          *  This provides a type gaurd ensuring that [[components]]
 
-          *  is non-null.
 
-          */
 
-         isTuple() {
 
-             return (this.baseType === "tuple");
 
-         }
 
-         /**
 
-          *  Returns true if %%this%% is an Indexable type.
 
-          *
 
-          *  This provides a type gaurd ensuring that [[indexed]]
 
-          *  is non-null.
 
-          */
 
-         isIndexable() {
 
-             return (this.indexed != null);
 
-         }
 
-         /**
 
-          *  Walks the **ParamType** with %%value%%, calling %%process%%
 
-          *  on each type, destructing the %%value%% recursively.
 
-          */
 
-         walk(value, process) {
 
-             if (this.isArray()) {
 
-                 if (!Array.isArray(value)) {
 
-                     throw new Error("invalid array value");
 
-                 }
 
-                 if (this.arrayLength !== -1 && value.length !== this.arrayLength) {
 
-                     throw new Error("array is wrong length");
 
-                 }
 
-                 const _this = this;
 
-                 return value.map((v) => (_this.arrayChildren.walk(v, process)));
 
-             }
 
-             if (this.isTuple()) {
 
-                 if (!Array.isArray(value)) {
 
-                     throw new Error("invalid tuple value");
 
-                 }
 
-                 if (value.length !== this.components.length) {
 
-                     throw new Error("array is wrong length");
 
-                 }
 
-                 const _this = this;
 
-                 return value.map((v, i) => (_this.components[i].walk(v, process)));
 
-             }
 
-             return process(this.type, value);
 
-         }
 
-         #walkAsync(promises, value, process, setValue) {
 
-             if (this.isArray()) {
 
-                 if (!Array.isArray(value)) {
 
-                     throw new Error("invalid array value");
 
-                 }
 
-                 if (this.arrayLength !== -1 && value.length !== this.arrayLength) {
 
-                     throw new Error("array is wrong length");
 
-                 }
 
-                 const childType = this.arrayChildren;
 
-                 const result = value.slice();
 
-                 result.forEach((value, index) => {
 
-                     childType.#walkAsync(promises, value, process, (value) => {
 
-                         result[index] = value;
 
-                     });
 
-                 });
 
-                 setValue(result);
 
-                 return;
 
-             }
 
-             if (this.isTuple()) {
 
-                 const components = this.components;
 
-                 // Convert the object into an array
 
-                 let result;
 
-                 if (Array.isArray(value)) {
 
-                     result = value.slice();
 
-                 }
 
-                 else {
 
-                     if (value == null || typeof (value) !== "object") {
 
-                         throw new Error("invalid tuple value");
 
-                     }
 
-                     result = components.map((param) => {
 
-                         if (!param.name) {
 
-                             throw new Error("cannot use object value with unnamed components");
 
-                         }
 
-                         if (!(param.name in value)) {
 
-                             throw new Error(`missing value for component ${param.name}`);
 
-                         }
 
-                         return value[param.name];
 
-                     });
 
-                 }
 
-                 if (result.length !== this.components.length) {
 
-                     throw new Error("array is wrong length");
 
-                 }
 
-                 result.forEach((value, index) => {
 
-                     components[index].#walkAsync(promises, value, process, (value) => {
 
-                         result[index] = value;
 
-                     });
 
-                 });
 
-                 setValue(result);
 
-                 return;
 
-             }
 
-             const result = process(this.type, value);
 
-             if (result.then) {
 
-                 promises.push((async function () { setValue(await result); })());
 
-             }
 
-             else {
 
-                 setValue(result);
 
-             }
 
-         }
 
-         /**
 
-          *  Walks the **ParamType** with %%value%%, asynchronously calling
 
-          *  %%process%% on each type, destructing the %%value%% recursively.
 
-          *
 
-          *  This can be used to resolve ENS names by walking and resolving each
 
-          *  ``"address"`` type.
 
-          */
 
-         async walkAsync(value, process) {
 
-             const promises = [];
 
-             const result = [value];
 
-             this.#walkAsync(promises, value, process, (value) => {
 
-                 result[0] = value;
 
-             });
 
-             if (promises.length) {
 
-                 await Promise.all(promises);
 
-             }
 
-             return result[0];
 
-         }
 
-         /**
 
-          *  Creates a new **ParamType** for %%obj%%.
 
-          *
 
-          *  If %%allowIndexed%% then the ``indexed`` keyword is permitted,
 
-          *  otherwise the ``indexed`` keyword will throw an error.
 
-          */
 
-         static from(obj, allowIndexed) {
 
-             if (ParamType.isParamType(obj)) {
 
-                 return obj;
 
-             }
 
-             if (typeof (obj) === "string") {
 
-                 try {
 
-                     return ParamType.from(lex(obj), allowIndexed);
 
-                 }
 
-                 catch (error) {
 
-                     assertArgument(false, "invalid param type", "obj", obj);
 
-                 }
 
-             }
 
-             else if (obj instanceof TokenString) {
 
-                 let type = "", baseType = "";
 
-                 let comps = null;
 
-                 if (consumeKeywords(obj, setify(["tuple"])).has("tuple") || obj.peekType("OPEN_PAREN")) {
 
-                     // Tuple
 
-                     baseType = "tuple";
 
-                     comps = obj.popParams().map((t) => ParamType.from(t));
 
-                     type = `tuple(${comps.map((c) => c.format()).join(",")})`;
 
-                 }
 
-                 else {
 
-                     // Normal
 
-                     type = verifyBasicType(obj.popType("TYPE"));
 
-                     baseType = type;
 
-                 }
 
-                 // Check for Array
 
-                 let arrayChildren = null;
 
-                 let arrayLength = null;
 
-                 while (obj.length && obj.peekType("BRACKET")) {
 
-                     const bracket = obj.pop(); //arrays[i];
 
-                     arrayChildren = new ParamType(_guard$2, "", type, baseType, null, comps, arrayLength, arrayChildren);
 
-                     arrayLength = bracket.value;
 
-                     type += bracket.text;
 
-                     baseType = "array";
 
-                     comps = null;
 
-                 }
 
-                 let indexed = null;
 
-                 const keywords = consumeKeywords(obj, KwModifiers);
 
-                 if (keywords.has("indexed")) {
 
-                     if (!allowIndexed) {
 
-                         throw new Error("");
 
-                     }
 
-                     indexed = true;
 
-                 }
 
-                 const name = (obj.peekType("ID") ? obj.pop().text : "");
 
-                 if (obj.length) {
 
-                     throw new Error("leftover tokens");
 
-                 }
 
-                 return new ParamType(_guard$2, name, type, baseType, indexed, comps, arrayLength, arrayChildren);
 
-             }
 
-             const name = obj.name;
 
-             assertArgument(!name || (typeof (name) === "string" && name.match(regexId)), "invalid name", "obj.name", name);
 
-             let indexed = obj.indexed;
 
-             if (indexed != null) {
 
-                 assertArgument(allowIndexed, "parameter cannot be indexed", "obj.indexed", obj.indexed);
 
-                 indexed = !!indexed;
 
-             }
 
-             let type = obj.type;
 
-             let arrayMatch = type.match(regexArrayType);
 
-             if (arrayMatch) {
 
-                 const arrayLength = parseInt(arrayMatch[2] || "-1");
 
-                 const arrayChildren = ParamType.from({
 
-                     type: arrayMatch[1],
 
-                     components: obj.components
 
-                 });
 
-                 return new ParamType(_guard$2, name || "", type, "array", indexed, null, arrayLength, arrayChildren);
 
-             }
 
-             if (type === "tuple" || type.startsWith("tuple(" /* fix: ) */) || type.startsWith("(" /* fix: ) */)) {
 
-                 const comps = (obj.components != null) ? obj.components.map((c) => ParamType.from(c)) : null;
 
-                 const tuple = new ParamType(_guard$2, name || "", type, "tuple", indexed, comps, null, null);
 
-                 // @TODO: use lexer to validate and normalize type
 
-                 return tuple;
 
-             }
 
-             type = verifyBasicType(obj.type);
 
-             return new ParamType(_guard$2, name || "", type, type, indexed, null, null, null);
 
-         }
 
-         /**
 
-          *  Returns true if %%value%% is a **ParamType**.
 
-          */
 
-         static isParamType(value) {
 
-             return (value && value[internal$1] === ParamTypeInternal);
 
-         }
 
-     }
 
-     /**
 
-      *  An abstract class to represent An individual fragment from a parse ABI.
 
-      */
 
-     class Fragment {
 
-         /**
 
-          *  The type of the fragment.
 
-          */
 
-         type;
 
-         /**
 
-          *  The inputs for the fragment.
 
-          */
 
-         inputs;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, type, inputs) {
 
-             assertPrivate(guard, _guard$2, "Fragment");
 
-             inputs = Object.freeze(inputs.slice());
 
-             defineProperties(this, { type, inputs });
 
-         }
 
-         /**
 
-          *  Creates a new **Fragment** for %%obj%%, wich can be any supported
 
-          *  ABI frgament type.
 
-          */
 
-         static from(obj) {
 
-             if (typeof (obj) === "string") {
 
-                 // Try parsing JSON...
 
-                 try {
 
-                     Fragment.from(JSON.parse(obj));
 
-                 }
 
-                 catch (e) { }
 
-                 // ...otherwise, use the human-readable lexer
 
-                 return Fragment.from(lex(obj));
 
-             }
 
-             if (obj instanceof TokenString) {
 
-                 // Human-readable ABI (already lexed)
 
-                 const type = obj.peekKeyword(KwTypes);
 
-                 switch (type) {
 
-                     case "constructor": return ConstructorFragment.from(obj);
 
-                     case "error": return ErrorFragment.from(obj);
 
-                     case "event": return EventFragment.from(obj);
 
-                     case "fallback":
 
-                     case "receive":
 
-                         return FallbackFragment.from(obj);
 
-                     case "function": return FunctionFragment.from(obj);
 
-                     case "struct": return StructFragment.from(obj);
 
-                 }
 
-             }
 
-             else if (typeof (obj) === "object") {
 
-                 // JSON ABI
 
-                 switch (obj.type) {
 
-                     case "constructor": return ConstructorFragment.from(obj);
 
-                     case "error": return ErrorFragment.from(obj);
 
-                     case "event": return EventFragment.from(obj);
 
-                     case "fallback":
 
-                     case "receive":
 
-                         return FallbackFragment.from(obj);
 
-                     case "function": return FunctionFragment.from(obj);
 
-                     case "struct": return StructFragment.from(obj);
 
-                 }
 
-                 assert(false, `unsupported type: ${obj.type}`, "UNSUPPORTED_OPERATION", {
 
-                     operation: "Fragment.from"
 
-                 });
 
-             }
 
-             assertArgument(false, "unsupported frgament object", "obj", obj);
 
-         }
 
-         /**
 
-          *  Returns true if %%value%% is a [[ConstructorFragment]].
 
-          */
 
-         static isConstructor(value) {
 
-             return ConstructorFragment.isFragment(value);
 
-         }
 
-         /**
 
-          *  Returns true if %%value%% is an [[ErrorFragment]].
 
-          */
 
-         static isError(value) {
 
-             return ErrorFragment.isFragment(value);
 
-         }
 
-         /**
 
-          *  Returns true if %%value%% is an [[EventFragment]].
 
-          */
 
-         static isEvent(value) {
 
-             return EventFragment.isFragment(value);
 
-         }
 
-         /**
 
-          *  Returns true if %%value%% is a [[FunctionFragment]].
 
-          */
 
-         static isFunction(value) {
 
-             return FunctionFragment.isFragment(value);
 
-         }
 
-         /**
 
-          *  Returns true if %%value%% is a [[StructFragment]].
 
-          */
 
-         static isStruct(value) {
 
-             return StructFragment.isFragment(value);
 
-         }
 
-     }
 
-     /**
 
-      *  An abstract class to represent An individual fragment
 
-      *  which has a name from a parse ABI.
 
-      */
 
-     class NamedFragment extends Fragment {
 
-         /**
 
-          *  The name of the fragment.
 
-          */
 
-         name;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, type, name, inputs) {
 
-             super(guard, type, inputs);
 
-             assertArgument(typeof (name) === "string" && name.match(regexId), "invalid identifier", "name", name);
 
-             inputs = Object.freeze(inputs.slice());
 
-             defineProperties(this, { name });
 
-         }
 
-     }
 
-     function joinParams(format, params) {
 
-         return "(" + params.map((p) => p.format(format)).join((format === "full") ? ", " : ",") + ")";
 
-     }
 
-     /**
 
-      *  A Fragment which represents a //Custom Error//.
 
-      */
 
-     class ErrorFragment extends NamedFragment {
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, name, inputs) {
 
-             super(guard, "error", name, inputs);
 
-             Object.defineProperty(this, internal$1, { value: ErrorFragmentInternal });
 
-         }
 
-         /**
 
-          *  The Custom Error selector.
 
-          */
 
-         get selector() {
 
-             return id(this.format("sighash")).substring(0, 10);
 
-         }
 
-         /**
 
-          *  Returns a string representation of this fragment as %%format%%.
 
-          */
 
-         format(format) {
 
-             if (format == null) {
 
-                 format = "sighash";
 
-             }
 
-             if (format === "json") {
 
-                 return JSON.stringify({
 
-                     type: "error",
 
-                     name: this.name,
 
-                     inputs: this.inputs.map((input) => JSON.parse(input.format(format))),
 
-                 });
 
-             }
 
-             const result = [];
 
-             if (format !== "sighash") {
 
-                 result.push("error");
 
-             }
 
-             result.push(this.name + joinParams(format, this.inputs));
 
-             return result.join(" ");
 
-         }
 
-         /**
 
-          *  Returns a new **ErrorFragment** for %%obj%%.
 
-          */
 
-         static from(obj) {
 
-             if (ErrorFragment.isFragment(obj)) {
 
-                 return obj;
 
-             }
 
-             if (typeof (obj) === "string") {
 
-                 return ErrorFragment.from(lex(obj));
 
-             }
 
-             else if (obj instanceof TokenString) {
 
-                 const name = consumeName("error", obj);
 
-                 const inputs = consumeParams(obj);
 
-                 consumeEoi(obj);
 
-                 return new ErrorFragment(_guard$2, name, inputs);
 
-             }
 
-             return new ErrorFragment(_guard$2, obj.name, obj.inputs ? obj.inputs.map(ParamType.from) : []);
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard if %%value%% is an
 
-          *  **ErrorFragment**.
 
-          */
 
-         static isFragment(value) {
 
-             return (value && value[internal$1] === ErrorFragmentInternal);
 
-         }
 
-     }
 
-     /**
 
-      *  A Fragment which represents an Event.
 
-      */
 
-     class EventFragment extends NamedFragment {
 
-         /**
 
-          *  Whether this event is anonymous.
 
-          */
 
-         anonymous;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, name, inputs, anonymous) {
 
-             super(guard, "event", name, inputs);
 
-             Object.defineProperty(this, internal$1, { value: EventFragmentInternal });
 
-             defineProperties(this, { anonymous });
 
-         }
 
-         /**
 
-          *  The Event topic hash.
 
-          */
 
-         get topicHash() {
 
-             return id(this.format("sighash"));
 
-         }
 
-         /**
 
-          *  Returns a string representation of this event as %%format%%.
 
-          */
 
-         format(format) {
 
-             if (format == null) {
 
-                 format = "sighash";
 
-             }
 
-             if (format === "json") {
 
-                 return JSON.stringify({
 
-                     type: "event",
 
-                     anonymous: this.anonymous,
 
-                     name: this.name,
 
-                     inputs: this.inputs.map((i) => JSON.parse(i.format(format)))
 
-                 });
 
-             }
 
-             const result = [];
 
-             if (format !== "sighash") {
 
-                 result.push("event");
 
-             }
 
-             result.push(this.name + joinParams(format, this.inputs));
 
-             if (format !== "sighash" && this.anonymous) {
 
-                 result.push("anonymous");
 
-             }
 
-             return result.join(" ");
 
-         }
 
-         /**
 
-          *  Return the topic hash for an event with %%name%% and %%params%%.
 
-          */
 
-         static getTopicHash(name, params) {
 
-             params = (params || []).map((p) => ParamType.from(p));
 
-             const fragment = new EventFragment(_guard$2, name, params, false);
 
-             return fragment.topicHash;
 
-         }
 
-         /**
 
-          *  Returns a new **EventFragment** for %%obj%%.
 
-          */
 
-         static from(obj) {
 
-             if (EventFragment.isFragment(obj)) {
 
-                 return obj;
 
-             }
 
-             if (typeof (obj) === "string") {
 
-                 try {
 
-                     return EventFragment.from(lex(obj));
 
-                 }
 
-                 catch (error) {
 
-                     assertArgument(false, "invalid event fragment", "obj", obj);
 
-                 }
 
-             }
 
-             else if (obj instanceof TokenString) {
 
-                 const name = consumeName("event", obj);
 
-                 const inputs = consumeParams(obj, true);
 
-                 const anonymous = !!consumeKeywords(obj, setify(["anonymous"])).has("anonymous");
 
-                 consumeEoi(obj);
 
-                 return new EventFragment(_guard$2, name, inputs, anonymous);
 
-             }
 
-             return new EventFragment(_guard$2, obj.name, obj.inputs ? obj.inputs.map((p) => ParamType.from(p, true)) : [], !!obj.anonymous);
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard if %%value%% is an
 
-          *  **EventFragment**.
 
-          */
 
-         static isFragment(value) {
 
-             return (value && value[internal$1] === EventFragmentInternal);
 
-         }
 
-     }
 
-     /**
 
-      *  A Fragment which represents a constructor.
 
-      */
 
-     class ConstructorFragment extends Fragment {
 
-         /**
 
-          *  Whether the constructor can receive an endowment.
 
-          */
 
-         payable;
 
-         /**
 
-          *  The recommended gas limit for deployment or ``null``.
 
-          */
 
-         gas;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, type, inputs, payable, gas) {
 
-             super(guard, type, inputs);
 
-             Object.defineProperty(this, internal$1, { value: ConstructorFragmentInternal });
 
-             defineProperties(this, { payable, gas });
 
-         }
 
-         /**
 
-          *  Returns a string representation of this constructor as %%format%%.
 
-          */
 
-         format(format) {
 
-             assert(format != null && format !== "sighash", "cannot format a constructor for sighash", "UNSUPPORTED_OPERATION", { operation: "format(sighash)" });
 
-             if (format === "json") {
 
-                 return JSON.stringify({
 
-                     type: "constructor",
 
-                     stateMutability: (this.payable ? "payable" : "undefined"),
 
-                     payable: this.payable,
 
-                     gas: ((this.gas != null) ? this.gas : undefined),
 
-                     inputs: this.inputs.map((i) => JSON.parse(i.format(format)))
 
-                 });
 
-             }
 
-             const result = [`constructor${joinParams(format, this.inputs)}`];
 
-             if (this.payable) {
 
-                 result.push("payable");
 
-             }
 
-             if (this.gas != null) {
 
-                 result.push(`@${this.gas.toString()}`);
 
-             }
 
-             return result.join(" ");
 
-         }
 
-         /**
 
-          *  Returns a new **ConstructorFragment** for %%obj%%.
 
-          */
 
-         static from(obj) {
 
-             if (ConstructorFragment.isFragment(obj)) {
 
-                 return obj;
 
-             }
 
-             if (typeof (obj) === "string") {
 
-                 try {
 
-                     return ConstructorFragment.from(lex(obj));
 
-                 }
 
-                 catch (error) {
 
-                     assertArgument(false, "invalid constuctor fragment", "obj", obj);
 
-                 }
 
-             }
 
-             else if (obj instanceof TokenString) {
 
-                 consumeKeywords(obj, setify(["constructor"]));
 
-                 const inputs = consumeParams(obj);
 
-                 const payable = !!consumeKeywords(obj, KwVisibDeploy).has("payable");
 
-                 const gas = consumeGas(obj);
 
-                 consumeEoi(obj);
 
-                 return new ConstructorFragment(_guard$2, "constructor", inputs, payable, gas);
 
-             }
 
-             return new ConstructorFragment(_guard$2, "constructor", obj.inputs ? obj.inputs.map(ParamType.from) : [], !!obj.payable, (obj.gas != null) ? obj.gas : null);
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard if %%value%% is a
 
-          *  **ConstructorFragment**.
 
-          */
 
-         static isFragment(value) {
 
-             return (value && value[internal$1] === ConstructorFragmentInternal);
 
-         }
 
-     }
 
-     /**
 
-      *  A Fragment which represents a method.
 
-      */
 
-     class FallbackFragment extends Fragment {
 
-         /**
 
-          *  If the function can be sent value during invocation.
 
-          */
 
-         payable;
 
-         constructor(guard, inputs, payable) {
 
-             super(guard, "fallback", inputs);
 
-             Object.defineProperty(this, internal$1, { value: FallbackFragmentInternal });
 
-             defineProperties(this, { payable });
 
-         }
 
-         /**
 
-          *  Returns a string representation of this fallback as %%format%%.
 
-          */
 
-         format(format) {
 
-             const type = ((this.inputs.length === 0) ? "receive" : "fallback");
 
-             if (format === "json") {
 
-                 const stateMutability = (this.payable ? "payable" : "nonpayable");
 
-                 return JSON.stringify({ type, stateMutability });
 
-             }
 
-             return `${type}()${this.payable ? " payable" : ""}`;
 
-         }
 
-         /**
 
-          *  Returns a new **FallbackFragment** for %%obj%%.
 
-          */
 
-         static from(obj) {
 
-             if (FallbackFragment.isFragment(obj)) {
 
-                 return obj;
 
-             }
 
-             if (typeof (obj) === "string") {
 
-                 try {
 
-                     return FallbackFragment.from(lex(obj));
 
-                 }
 
-                 catch (error) {
 
-                     assertArgument(false, "invalid fallback fragment", "obj", obj);
 
-                 }
 
-             }
 
-             else if (obj instanceof TokenString) {
 
-                 const errorObj = obj.toString();
 
-                 const topIsValid = obj.peekKeyword(setify(["fallback", "receive"]));
 
-                 assertArgument(topIsValid, "type must be fallback or receive", "obj", errorObj);
 
-                 const type = obj.popKeyword(setify(["fallback", "receive"]));
 
-                 // receive()
 
-                 if (type === "receive") {
 
-                     const inputs = consumeParams(obj);
 
-                     assertArgument(inputs.length === 0, `receive cannot have arguments`, "obj.inputs", inputs);
 
-                     consumeKeywords(obj, setify(["payable"]));
 
-                     consumeEoi(obj);
 
-                     return new FallbackFragment(_guard$2, [], true);
 
-                 }
 
-                 // fallback() [payable]
 
-                 // fallback(bytes) [payable] returns (bytes)
 
-                 let inputs = consumeParams(obj);
 
-                 if (inputs.length) {
 
-                     assertArgument(inputs.length === 1 && inputs[0].type === "bytes", "invalid fallback inputs", "obj.inputs", inputs.map((i) => i.format("minimal")).join(", "));
 
-                 }
 
-                 else {
 
-                     inputs = [ParamType.from("bytes")];
 
-                 }
 
-                 const mutability = consumeMutability(obj);
 
-                 assertArgument(mutability === "nonpayable" || mutability === "payable", "fallback cannot be constants", "obj.stateMutability", mutability);
 
-                 if (consumeKeywords(obj, setify(["returns"])).has("returns")) {
 
-                     const outputs = consumeParams(obj);
 
-                     assertArgument(outputs.length === 1 && outputs[0].type === "bytes", "invalid fallback outputs", "obj.outputs", outputs.map((i) => i.format("minimal")).join(", "));
 
-                 }
 
-                 consumeEoi(obj);
 
-                 return new FallbackFragment(_guard$2, inputs, mutability === "payable");
 
-             }
 
-             if (obj.type === "receive") {
 
-                 return new FallbackFragment(_guard$2, [], true);
 
-             }
 
-             if (obj.type === "fallback") {
 
-                 const inputs = [ParamType.from("bytes")];
 
-                 const payable = (obj.stateMutability === "payable");
 
-                 return new FallbackFragment(_guard$2, inputs, payable);
 
-             }
 
-             assertArgument(false, "invalid fallback description", "obj", obj);
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard if %%value%% is a
 
-          *  **FallbackFragment**.
 
-          */
 
-         static isFragment(value) {
 
-             return (value && value[internal$1] === FallbackFragmentInternal);
 
-         }
 
-     }
 
-     /**
 
-      *  A Fragment which represents a method.
 
-      */
 
-     class FunctionFragment extends NamedFragment {
 
-         /**
 
-          *  If the function is constant (e.g. ``pure`` or ``view`` functions).
 
-          */
 
-         constant;
 
-         /**
 
-          *  The returned types for the result of calling this function.
 
-          */
 
-         outputs;
 
-         /**
 
-          *  The state mutability (e.g. ``payable``, ``nonpayable``, ``view``
 
-          *  or ``pure``)
 
-          */
 
-         stateMutability;
 
-         /**
 
-          *  If the function can be sent value during invocation.
 
-          */
 
-         payable;
 
-         /**
 
-          *  The recommended gas limit to send when calling this function.
 
-          */
 
-         gas;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, name, stateMutability, inputs, outputs, gas) {
 
-             super(guard, "function", name, inputs);
 
-             Object.defineProperty(this, internal$1, { value: FunctionFragmentInternal });
 
-             outputs = Object.freeze(outputs.slice());
 
-             const constant = (stateMutability === "view" || stateMutability === "pure");
 
-             const payable = (stateMutability === "payable");
 
-             defineProperties(this, { constant, gas, outputs, payable, stateMutability });
 
-         }
 
-         /**
 
-          *  The Function selector.
 
-          */
 
-         get selector() {
 
-             return id(this.format("sighash")).substring(0, 10);
 
-         }
 
-         /**
 
-          *  Returns a string representation of this function as %%format%%.
 
-          */
 
-         format(format) {
 
-             if (format == null) {
 
-                 format = "sighash";
 
-             }
 
-             if (format === "json") {
 
-                 return JSON.stringify({
 
-                     type: "function",
 
-                     name: this.name,
 
-                     constant: this.constant,
 
-                     stateMutability: ((this.stateMutability !== "nonpayable") ? this.stateMutability : undefined),
 
-                     payable: this.payable,
 
-                     gas: ((this.gas != null) ? this.gas : undefined),
 
-                     inputs: this.inputs.map((i) => JSON.parse(i.format(format))),
 
-                     outputs: this.outputs.map((o) => JSON.parse(o.format(format))),
 
-                 });
 
-             }
 
-             const result = [];
 
-             if (format !== "sighash") {
 
-                 result.push("function");
 
-             }
 
-             result.push(this.name + joinParams(format, this.inputs));
 
-             if (format !== "sighash") {
 
-                 if (this.stateMutability !== "nonpayable") {
 
-                     result.push(this.stateMutability);
 
-                 }
 
-                 if (this.outputs && this.outputs.length) {
 
-                     result.push("returns");
 
-                     result.push(joinParams(format, this.outputs));
 
-                 }
 
-                 if (this.gas != null) {
 
-                     result.push(`@${this.gas.toString()}`);
 
-                 }
 
-             }
 
-             return result.join(" ");
 
-         }
 
-         /**
 
-          *  Return the selector for a function with %%name%% and %%params%%.
 
-          */
 
-         static getSelector(name, params) {
 
-             params = (params || []).map((p) => ParamType.from(p));
 
-             const fragment = new FunctionFragment(_guard$2, name, "view", params, [], null);
 
-             return fragment.selector;
 
-         }
 
-         /**
 
-          *  Returns a new **FunctionFragment** for %%obj%%.
 
-          */
 
-         static from(obj) {
 
-             if (FunctionFragment.isFragment(obj)) {
 
-                 return obj;
 
-             }
 
-             if (typeof (obj) === "string") {
 
-                 try {
 
-                     return FunctionFragment.from(lex(obj));
 
-                 }
 
-                 catch (error) {
 
-                     assertArgument(false, "invalid function fragment", "obj", obj);
 
-                 }
 
-             }
 
-             else if (obj instanceof TokenString) {
 
-                 const name = consumeName("function", obj);
 
-                 const inputs = consumeParams(obj);
 
-                 const mutability = consumeMutability(obj);
 
-                 let outputs = [];
 
-                 if (consumeKeywords(obj, setify(["returns"])).has("returns")) {
 
-                     outputs = consumeParams(obj);
 
-                 }
 
-                 const gas = consumeGas(obj);
 
-                 consumeEoi(obj);
 
-                 return new FunctionFragment(_guard$2, name, mutability, inputs, outputs, gas);
 
-             }
 
-             let stateMutability = obj.stateMutability;
 
-             // Use legacy Solidity ABI logic if stateMutability is missing
 
-             if (stateMutability == null) {
 
-                 stateMutability = "payable";
 
-                 if (typeof (obj.constant) === "boolean") {
 
-                     stateMutability = "view";
 
-                     if (!obj.constant) {
 
-                         stateMutability = "payable";
 
-                         if (typeof (obj.payable) === "boolean" && !obj.payable) {
 
-                             stateMutability = "nonpayable";
 
-                         }
 
-                     }
 
-                 }
 
-                 else if (typeof (obj.payable) === "boolean" && !obj.payable) {
 
-                     stateMutability = "nonpayable";
 
-                 }
 
-             }
 
-             // @TODO: verifyState for stateMutability (e.g. throw if
 
-             //        payable: false but stateMutability is "nonpayable")
 
-             return new FunctionFragment(_guard$2, obj.name, stateMutability, obj.inputs ? obj.inputs.map(ParamType.from) : [], obj.outputs ? obj.outputs.map(ParamType.from) : [], (obj.gas != null) ? obj.gas : null);
 
-         }
 
-         /**
 
-          *  Returns ``true`` and provides a type guard if %%value%% is a
 
-          *  **FunctionFragment**.
 
-          */
 
-         static isFragment(value) {
 
-             return (value && value[internal$1] === FunctionFragmentInternal);
 
-         }
 
-     }
 
-     /**
 
-      *  A Fragment which represents a structure.
 
-      */
 
-     class StructFragment extends NamedFragment {
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, name, inputs) {
 
-             super(guard, "struct", name, inputs);
 
-             Object.defineProperty(this, internal$1, { value: StructFragmentInternal });
 
-         }
 
-         /**
 
-          *  Returns a string representation of this struct as %%format%%.
 
-          */
 
-         format() {
 
-             throw new Error("@TODO");
 
-         }
 
-         /**
 
-          *  Returns a new **StructFragment** for %%obj%%.
 
-          */
 
-         static from(obj) {
 
-             if (typeof (obj) === "string") {
 
-                 try {
 
-                     return StructFragment.from(lex(obj));
 
-                 }
 
-                 catch (error) {
 
-                     assertArgument(false, "invalid struct fragment", "obj", obj);
 
-                 }
 
-             }
 
-             else if (obj instanceof TokenString) {
 
-                 const name = consumeName("struct", obj);
 
-                 const inputs = consumeParams(obj);
 
-                 consumeEoi(obj);
 
-                 return new StructFragment(_guard$2, name, inputs);
 
-             }
 
-             return new StructFragment(_guard$2, obj.name, obj.inputs ? obj.inputs.map(ParamType.from) : []);
 
-         }
 
-         // @TODO: fix this return type
 
-         /**
 
-          *  Returns ``true`` and provides a type guard if %%value%% is a
 
-          *  **StructFragment**.
 
-          */
 
-         static isFragment(value) {
 
-             return (value && value[internal$1] === StructFragmentInternal);
 
-         }
 
-     }
 
-     /**
 
-      *  When sending values to or receiving values from a [[Contract]], the
 
-      *  data is generally encoded using the [ABI standard](link-solc-abi).
 
-      *
 
-      *  The AbiCoder provides a utility to encode values to ABI data and
 
-      *  decode values from ABI data.
 
-      *
 
-      *  Most of the time, developers should favour the [[Contract]] class,
 
-      *  which further abstracts a lot of the finer details of ABI data.
 
-      *
 
-      *  @_section api/abi/abi-coder:ABI Encoding
 
-      */
 
-     // See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
 
-     // https://docs.soliditylang.org/en/v0.8.17/control-structures.html
 
-     const PanicReasons$1 = new Map();
 
-     PanicReasons$1.set(0x00, "GENERIC_PANIC");
 
-     PanicReasons$1.set(0x01, "ASSERT_FALSE");
 
-     PanicReasons$1.set(0x11, "OVERFLOW");
 
-     PanicReasons$1.set(0x12, "DIVIDE_BY_ZERO");
 
-     PanicReasons$1.set(0x21, "ENUM_RANGE_ERROR");
 
-     PanicReasons$1.set(0x22, "BAD_STORAGE_DATA");
 
-     PanicReasons$1.set(0x31, "STACK_UNDERFLOW");
 
-     PanicReasons$1.set(0x32, "ARRAY_RANGE_ERROR");
 
-     PanicReasons$1.set(0x41, "OUT_OF_MEMORY");
 
-     PanicReasons$1.set(0x51, "UNINITIALIZED_FUNCTION_CALL");
 
-     const paramTypeBytes = new RegExp(/^bytes([0-9]*)$/);
 
-     const paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/);
 
-     let defaultCoder = null;
 
-     let defaultMaxInflation = 1024;
 
-     function getBuiltinCallException(action, tx, data, abiCoder) {
 
-         let message = "missing revert data";
 
-         let reason = null;
 
-         const invocation = null;
 
-         let revert = null;
 
-         if (data) {
 
-             message = "execution reverted";
 
-             const bytes = getBytes(data);
 
-             data = hexlify(data);
 
-             if (bytes.length === 0) {
 
-                 message += " (no data present; likely require(false) occurred";
 
-                 reason = "require(false)";
 
-             }
 
-             else if (bytes.length % 32 !== 4) {
 
-                 message += " (could not decode reason; invalid data length)";
 
-             }
 
-             else if (hexlify(bytes.slice(0, 4)) === "0x08c379a0") {
 
-                 // Error(string)
 
-                 try {
 
-                     reason = abiCoder.decode(["string"], bytes.slice(4))[0];
 
-                     revert = {
 
-                         signature: "Error(string)",
 
-                         name: "Error",
 
-                         args: [reason]
 
-                     };
 
-                     message += `: ${JSON.stringify(reason)}`;
 
-                 }
 
-                 catch (error) {
 
-                     message += " (could not decode reason; invalid string data)";
 
-                 }
 
-             }
 
-             else if (hexlify(bytes.slice(0, 4)) === "0x4e487b71") {
 
-                 // Panic(uint256)
 
-                 try {
 
-                     const code = Number(abiCoder.decode(["uint256"], bytes.slice(4))[0]);
 
-                     revert = {
 
-                         signature: "Panic(uint256)",
 
-                         name: "Panic",
 
-                         args: [code]
 
-                     };
 
-                     reason = `Panic due to ${PanicReasons$1.get(code) || "UNKNOWN"}(${code})`;
 
-                     message += `: ${reason}`;
 
-                 }
 
-                 catch (error) {
 
-                     message += " (could not decode panic code)";
 
-                 }
 
-             }
 
-             else {
 
-                 message += " (unknown custom error)";
 
-             }
 
-         }
 
-         const transaction = {
 
-             to: (tx.to ? getAddress(tx.to) : null),
 
-             data: (tx.data || "0x")
 
-         };
 
-         if (tx.from) {
 
-             transaction.from = getAddress(tx.from);
 
-         }
 
-         return makeError(message, "CALL_EXCEPTION", {
 
-             action, data, reason, transaction, invocation, revert
 
-         });
 
-     }
 
-     /**
 
-      *  The **AbiCoder** is a low-level class responsible for encoding JavaScript
 
-      *  values into binary data and decoding binary data into JavaScript values.
 
-      */
 
-     class AbiCoder {
 
-         #getCoder(param) {
 
-             if (param.isArray()) {
 
-                 return new ArrayCoder(this.#getCoder(param.arrayChildren), param.arrayLength, param.name);
 
-             }
 
-             if (param.isTuple()) {
 
-                 return new TupleCoder(param.components.map((c) => this.#getCoder(c)), param.name);
 
-             }
 
-             switch (param.baseType) {
 
-                 case "address":
 
-                     return new AddressCoder(param.name);
 
-                 case "bool":
 
-                     return new BooleanCoder(param.name);
 
-                 case "string":
 
-                     return new StringCoder(param.name);
 
-                 case "bytes":
 
-                     return new BytesCoder(param.name);
 
-                 case "":
 
-                     return new NullCoder(param.name);
 
-             }
 
-             // u?int[0-9]*
 
-             let match = param.type.match(paramTypeNumber);
 
-             if (match) {
 
-                 let size = parseInt(match[2] || "256");
 
-                 assertArgument(size !== 0 && size <= 256 && (size % 8) === 0, "invalid " + match[1] + " bit length", "param", param);
 
-                 return new NumberCoder(size / 8, (match[1] === "int"), param.name);
 
-             }
 
-             // bytes[0-9]+
 
-             match = param.type.match(paramTypeBytes);
 
-             if (match) {
 
-                 let size = parseInt(match[1]);
 
-                 assertArgument(size !== 0 && size <= 32, "invalid bytes length", "param", param);
 
-                 return new FixedBytesCoder(size, param.name);
 
-             }
 
-             assertArgument(false, "invalid type", "type", param.type);
 
-         }
 
-         /**
 
-          *  Get the default values for the given %%types%%.
 
-          *
 
-          *  For example, a ``uint`` is by default ``0`` and ``bool``
 
-          *  is by default ``false``.
 
-          */
 
-         getDefaultValue(types) {
 
-             const coders = types.map((type) => this.#getCoder(ParamType.from(type)));
 
-             const coder = new TupleCoder(coders, "_");
 
-             return coder.defaultValue();
 
-         }
 
-         /**
 
-          *  Encode the %%values%% as the %%types%% into ABI data.
 
-          *
 
-          *  @returns DataHexstring
 
-          */
 
-         encode(types, values) {
 
-             assertArgumentCount(values.length, types.length, "types/values length mismatch");
 
-             const coders = types.map((type) => this.#getCoder(ParamType.from(type)));
 
-             const coder = (new TupleCoder(coders, "_"));
 
-             const writer = new Writer();
 
-             coder.encode(writer, values);
 
-             return writer.data;
 
-         }
 
-         /**
 
-          *  Decode the ABI %%data%% as the %%types%% into values.
 
-          *
 
-          *  If %%loose%% decoding is enabled, then strict padding is
 
-          *  not enforced. Some older versions of Solidity incorrectly
 
-          *  padded event data emitted from ``external`` functions.
 
-          */
 
-         decode(types, data, loose) {
 
-             const coders = types.map((type) => this.#getCoder(ParamType.from(type)));
 
-             const coder = new TupleCoder(coders, "_");
 
-             return coder.decode(new Reader(data, loose, defaultMaxInflation));
 
-         }
 
-         static _setDefaultMaxInflation(value) {
 
-             assertArgument(typeof (value) === "number" && Number.isInteger(value), "invalid defaultMaxInflation factor", "value", value);
 
-             defaultMaxInflation = value;
 
-         }
 
-         /**
 
-          *  Returns the shared singleton instance of a default [[AbiCoder]].
 
-          *
 
-          *  On the first call, the instance is created internally.
 
-          */
 
-         static defaultAbiCoder() {
 
-             if (defaultCoder == null) {
 
-                 defaultCoder = new AbiCoder();
 
-             }
 
-             return defaultCoder;
 
-         }
 
-         /**
 
-          *  Returns an ethers-compatible [[CallExceptionError]] Error for the given
 
-          *  result %%data%% for the [[CallExceptionAction]] %%action%% against
 
-          *  the Transaction %%tx%%.
 
-          */
 
-         static getBuiltinCallException(action, tx, data) {
 
-             return getBuiltinCallException(action, tx, data, AbiCoder.defaultAbiCoder());
 
-         }
 
-     }
 
-     /**
 
-      *  About bytes32 strings...
 
-      *
 
-      *  @_docloc: api/utils:Bytes32 Strings
 
-      */
 
-     /**
 
-      *  Encodes %%text%% as a Bytes32 string.
 
-      */
 
-     function encodeBytes32String(text) {
 
-         // Get the bytes
 
-         const bytes = toUtf8Bytes(text);
 
-         // Check we have room for null-termination
 
-         if (bytes.length > 31) {
 
-             throw new Error("bytes32 string must be less than 32 bytes");
 
-         }
 
-         // Zero-pad (implicitly null-terminates)
 
-         return zeroPadBytes(bytes, 32);
 
-     }
 
-     /**
 
-      *  Encodes the Bytes32-encoded %%bytes%% into a string.
 
-      */
 
-     function decodeBytes32String(_bytes) {
 
-         const data = getBytes(_bytes, "bytes");
 
-         // Must be 32 bytes with a null-termination
 
-         if (data.length !== 32) {
 
-             throw new Error("invalid bytes32 - not 32 bytes long");
 
-         }
 
-         if (data[31] !== 0) {
 
-             throw new Error("invalid bytes32 string - no null terminator");
 
-         }
 
-         // Find the null termination
 
-         let length = 31;
 
-         while (data[length - 1] === 0) {
 
-             length--;
 
-         }
 
-         // Determine the string value
 
-         return toUtf8String(data.slice(0, length));
 
-     }
 
-     /**
 
-      *  The Interface class is a low-level class that accepts an
 
-      *  ABI and provides all the necessary functionality to encode
 
-      *  and decode paramaters to and results from methods, events
 
-      *  and errors.
 
-      *
 
-      *  It also provides several convenience methods to automatically
 
-      *  search and find matching transactions and events to parse them.
 
-      *
 
-      *  @_subsection api/abi:Interfaces  [interfaces]
 
-      */
 
-     /**
 
-      *  When using the [[Interface-parseLog]] to automatically match a Log to its event
 
-      *  for parsing, a **LogDescription** is returned.
 
-      */
 
-     class LogDescription {
 
-         /**
 
-          *  The matching fragment for the ``topic0``.
 
-          */
 
-         fragment;
 
-         /**
 
-          *  The name of the Event.
 
-          */
 
-         name;
 
-         /**
 
-          *  The full Event signature.
 
-          */
 
-         signature;
 
-         /**
 
-          *  The topic hash for the Event.
 
-          */
 
-         topic;
 
-         /**
 
-          *  The arguments passed into the Event with ``emit``.
 
-          */
 
-         args;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(fragment, topic, args) {
 
-             const name = fragment.name, signature = fragment.format();
 
-             defineProperties(this, {
 
-                 fragment, name, signature, topic, args
 
-             });
 
-         }
 
-     }
 
-     /**
 
-      *  When using the [[Interface-parseTransaction]] to automatically match
 
-      *  a transaction data to its function for parsing,
 
-      *  a **TransactionDescription** is returned.
 
-      */
 
-     class TransactionDescription {
 
-         /**
 
-          *  The matching fragment from the transaction ``data``.
 
-          */
 
-         fragment;
 
-         /**
 
-          *  The name of the Function from the transaction ``data``.
 
-          */
 
-         name;
 
-         /**
 
-          *  The arguments passed to the Function from the transaction ``data``.
 
-          */
 
-         args;
 
-         /**
 
-          *  The full Function signature from the transaction ``data``.
 
-          */
 
-         signature;
 
-         /**
 
-          *  The selector for the Function from the transaction ``data``.
 
-          */
 
-         selector;
 
-         /**
 
-          *  The ``value`` (in wei) from the transaction.
 
-          */
 
-         value;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(fragment, selector, args, value) {
 
-             const name = fragment.name, signature = fragment.format();
 
-             defineProperties(this, {
 
-                 fragment, name, args, signature, selector, value
 
-             });
 
-         }
 
-     }
 
-     /**
 
-      *  When using the [[Interface-parseError]] to automatically match an
 
-      *  error for a call result for parsing, an **ErrorDescription** is returned.
 
-      */
 
-     class ErrorDescription {
 
-         /**
 
-          *  The matching fragment.
 
-          */
 
-         fragment;
 
-         /**
 
-          *  The name of the Error.
 
-          */
 
-         name;
 
-         /**
 
-          *  The arguments passed to the Error with ``revert``.
 
-          */
 
-         args;
 
-         /**
 
-          *  The full Error signature.
 
-          */
 
-         signature;
 
-         /**
 
-          *  The selector for the Error.
 
-          */
 
-         selector;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(fragment, selector, args) {
 
-             const name = fragment.name, signature = fragment.format();
 
-             defineProperties(this, {
 
-                 fragment, name, args, signature, selector
 
-             });
 
-         }
 
-     }
 
-     /**
 
-      *  An **Indexed** is used as a value when a value that does not
 
-      *  fit within a topic (i.e. not a fixed-length, 32-byte type). It
 
-      *  is the ``keccak256`` of the value, and used for types such as
 
-      *  arrays, tuples, bytes and strings.
 
-      */
 
-     class Indexed {
 
-         /**
 
-          *  The ``keccak256`` of the value logged.
 
-          */
 
-         hash;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         _isIndexed;
 
-         /**
 
-          *  Returns ``true`` if %%value%% is an **Indexed**.
 
-          *
 
-          *  This provides a Type Guard for property access.
 
-          */
 
-         static isIndexed(value) {
 
-             return !!(value && value._isIndexed);
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(hash) {
 
-             defineProperties(this, { hash, _isIndexed: true });
 
-         }
 
-     }
 
-     // https://docs.soliditylang.org/en/v0.8.13/control-structures.html?highlight=panic#panic-via-assert-and-error-via-require
 
-     const PanicReasons = {
 
-         "0": "generic panic",
 
-         "1": "assert(false)",
 
-         "17": "arithmetic overflow",
 
-         "18": "division or modulo by zero",
 
-         "33": "enum overflow",
 
-         "34": "invalid encoded storage byte array accessed",
 
-         "49": "out-of-bounds array access; popping on an empty array",
 
-         "50": "out-of-bounds access of an array or bytesN",
 
-         "65": "out of memory",
 
-         "81": "uninitialized function",
 
-     };
 
-     const BuiltinErrors = {
 
-         "0x08c379a0": {
 
-             signature: "Error(string)",
 
-             name: "Error",
 
-             inputs: ["string"],
 
-             reason: (message) => {
 
-                 return `reverted with reason string ${JSON.stringify(message)}`;
 
-             }
 
-         },
 
-         "0x4e487b71": {
 
-             signature: "Panic(uint256)",
 
-             name: "Panic",
 
-             inputs: ["uint256"],
 
-             reason: (code) => {
 
-                 let reason = "unknown panic code";
 
-                 if (code >= 0 && code <= 0xff && PanicReasons[code.toString()]) {
 
-                     reason = PanicReasons[code.toString()];
 
-                 }
 
-                 return `reverted with panic code 0x${code.toString(16)} (${reason})`;
 
-             }
 
-         }
 
-     };
 
-     /**
 
-      *  An Interface abstracts many of the low-level details for
 
-      *  encoding and decoding the data on the blockchain.
 
-      *
 
-      *  An ABI provides information on how to encode data to send to
 
-      *  a Contract, how to decode the results and events and how to
 
-      *  interpret revert errors.
 
-      *
 
-      *  The ABI can be specified by [any supported format](InterfaceAbi).
 
-      */
 
-     class Interface {
 
-         /**
 
-          *  All the Contract ABI members (i.e. methods, events, errors, etc).
 
-          */
 
-         fragments;
 
-         /**
 
-          *  The Contract constructor.
 
-          */
 
-         deploy;
 
-         /**
 
-          *  The Fallback method, if any.
 
-          */
 
-         fallback;
 
-         /**
 
-          *  If receiving ether is supported.
 
-          */
 
-         receive;
 
-         #errors;
 
-         #events;
 
-         #functions;
 
-         //    #structs: Map<string, StructFragment>;
 
-         #abiCoder;
 
-         /**
 
-          *  Create a new Interface for the %%fragments%%.
 
-          */
 
-         constructor(fragments) {
 
-             let abi = [];
 
-             if (typeof (fragments) === "string") {
 
-                 abi = JSON.parse(fragments);
 
-             }
 
-             else {
 
-                 abi = fragments;
 
-             }
 
-             this.#functions = new Map();
 
-             this.#errors = new Map();
 
-             this.#events = new Map();
 
-             //        this.#structs = new Map();
 
-             const frags = [];
 
-             for (const a of abi) {
 
-                 try {
 
-                     frags.push(Fragment.from(a));
 
-                 }
 
-                 catch (error) {
 
-                     console.log(`[Warning] Invalid Fragment ${JSON.stringify(a)}:`, error.message);
 
-                 }
 
-             }
 
-             defineProperties(this, {
 
-                 fragments: Object.freeze(frags)
 
-             });
 
-             let fallback = null;
 
-             let receive = false;
 
-             this.#abiCoder = this.getAbiCoder();
 
-             // Add all fragments by their signature
 
-             this.fragments.forEach((fragment, index) => {
 
-                 let bucket;
 
-                 switch (fragment.type) {
 
-                     case "constructor":
 
-                         if (this.deploy) {
 
-                             console.log("duplicate definition - constructor");
 
-                             return;
 
-                         }
 
-                         //checkNames(fragment, "input", fragment.inputs);
 
-                         defineProperties(this, { deploy: fragment });
 
-                         return;
 
-                     case "fallback":
 
-                         if (fragment.inputs.length === 0) {
 
-                             receive = true;
 
-                         }
 
-                         else {
 
-                             assertArgument(!fallback || fragment.payable !== fallback.payable, "conflicting fallback fragments", `fragments[${index}]`, fragment);
 
-                             fallback = fragment;
 
-                             receive = fallback.payable;
 
-                         }
 
-                         return;
 
-                     case "function":
 
-                         //checkNames(fragment, "input", fragment.inputs);
 
-                         //checkNames(fragment, "output", (<FunctionFragment>fragment).outputs);
 
-                         bucket = this.#functions;
 
-                         break;
 
-                     case "event":
 
-                         //checkNames(fragment, "input", fragment.inputs);
 
-                         bucket = this.#events;
 
-                         break;
 
-                     case "error":
 
-                         bucket = this.#errors;
 
-                         break;
 
-                     default:
 
-                         return;
 
-                 }
 
-                 // Two identical entries; ignore it
 
-                 const signature = fragment.format();
 
-                 if (bucket.has(signature)) {
 
-                     return;
 
-                 }
 
-                 bucket.set(signature, fragment);
 
-             });
 
-             // If we do not have a constructor add a default
 
-             if (!this.deploy) {
 
-                 defineProperties(this, {
 
-                     deploy: ConstructorFragment.from("constructor()")
 
-                 });
 
-             }
 
-             defineProperties(this, { fallback, receive });
 
-         }
 
-         /**
 
-          *  Returns the entire Human-Readable ABI, as an array of
 
-          *  signatures, optionally as %%minimal%% strings, which
 
-          *  removes parameter names and unneceesary spaces.
 
-          */
 
-         format(minimal) {
 
-             const format = (minimal ? "minimal" : "full");
 
-             const abi = this.fragments.map((f) => f.format(format));
 
-             return abi;
 
-         }
 
-         /**
 
-          *  Return the JSON-encoded ABI. This is the format Solidiy
 
-          *  returns.
 
-          */
 
-         formatJson() {
 
-             const abi = this.fragments.map((f) => f.format("json"));
 
-             // We need to re-bundle the JSON fragments a bit
 
-             return JSON.stringify(abi.map((j) => JSON.parse(j)));
 
-         }
 
-         /**
 
-          *  The ABI coder that will be used to encode and decode binary
 
-          *  data.
 
-          */
 
-         getAbiCoder() {
 
-             return AbiCoder.defaultAbiCoder();
 
-         }
 
-         // Find a function definition by any means necessary (unless it is ambiguous)
 
-         #getFunction(key, values, forceUnique) {
 
-             // Selector
 
-             if (isHexString(key)) {
 
-                 const selector = key.toLowerCase();
 
-                 for (const fragment of this.#functions.values()) {
 
-                     if (selector === fragment.selector) {
 
-                         return fragment;
 
-                     }
 
-                 }
 
-                 return null;
 
-             }
 
-             // It is a bare name, look up the function (will return null if ambiguous)
 
-             if (key.indexOf("(") === -1) {
 
-                 const matching = [];
 
-                 for (const [name, fragment] of this.#functions) {
 
-                     if (name.split("(" /* fix:) */)[0] === key) {
 
-                         matching.push(fragment);
 
-                     }
 
-                 }
 
-                 if (values) {
 
-                     const lastValue = (values.length > 0) ? values[values.length - 1] : null;
 
-                     let valueLength = values.length;
 
-                     let allowOptions = true;
 
-                     if (Typed.isTyped(lastValue) && lastValue.type === "overrides") {
 
-                         allowOptions = false;
 
-                         valueLength--;
 
-                     }
 
-                     // Remove all matches that don't have a compatible length. The args
 
-                     // may contain an overrides, so the match may have n or n - 1 parameters
 
-                     for (let i = matching.length - 1; i >= 0; i--) {
 
-                         const inputs = matching[i].inputs.length;
 
-                         if (inputs !== valueLength && (!allowOptions || inputs !== valueLength - 1)) {
 
-                             matching.splice(i, 1);
 
-                         }
 
-                     }
 
-                     // Remove all matches that don't match the Typed signature
 
-                     for (let i = matching.length - 1; i >= 0; i--) {
 
-                         const inputs = matching[i].inputs;
 
-                         for (let j = 0; j < values.length; j++) {
 
-                             // Not a typed value
 
-                             if (!Typed.isTyped(values[j])) {
 
-                                 continue;
 
-                             }
 
-                             // We are past the inputs
 
-                             if (j >= inputs.length) {
 
-                                 if (values[j].type === "overrides") {
 
-                                     continue;
 
-                                 }
 
-                                 matching.splice(i, 1);
 
-                                 break;
 
-                             }
 
-                             // Make sure the value type matches the input type
 
-                             if (values[j].type !== inputs[j].baseType) {
 
-                                 matching.splice(i, 1);
 
-                                 break;
 
-                             }
 
-                         }
 
-                     }
 
-                 }
 
-                 // We found a single matching signature with an overrides, but the
 
-                 // last value is something that cannot possibly be an options
 
-                 if (matching.length === 1 && values && values.length !== matching[0].inputs.length) {
 
-                     const lastArg = values[values.length - 1];
 
-                     if (lastArg == null || Array.isArray(lastArg) || typeof (lastArg) !== "object") {
 
-                         matching.splice(0, 1);
 
-                     }
 
-                 }
 
-                 if (matching.length === 0) {
 
-                     return null;
 
-                 }
 
-                 if (matching.length > 1 && forceUnique) {
 
-                     const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
 
-                     assertArgument(false, `ambiguous function description (i.e. matches ${matchStr})`, "key", key);
 
-                 }
 
-                 return matching[0];
 
-             }
 
-             // Normalize the signature and lookup the function
 
-             const result = this.#functions.get(FunctionFragment.from(key).format());
 
-             if (result) {
 
-                 return result;
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  Get the function name for %%key%%, which may be a function selector,
 
-          *  function name or function signature that belongs to the ABI.
 
-          */
 
-         getFunctionName(key) {
 
-             const fragment = this.#getFunction(key, null, false);
 
-             assertArgument(fragment, "no matching function", "key", key);
 
-             return fragment.name;
 
-         }
 
-         /**
 
-          *  Returns true if %%key%% (a function selector, function name or
 
-          *  function signature) is present in the ABI.
 
-          *
 
-          *  In the case of a function name, the name may be ambiguous, so
 
-          *  accessing the [[FunctionFragment]] may require refinement.
 
-          */
 
-         hasFunction(key) {
 
-             return !!this.#getFunction(key, null, false);
 
-         }
 
-         /**
 
-          *  Get the [[FunctionFragment]] for %%key%%, which may be a function
 
-          *  selector, function name or function signature that belongs to the ABI.
 
-          *
 
-          *  If %%values%% is provided, it will use the Typed API to handle
 
-          *  ambiguous cases where multiple functions match by name.
 
-          *
 
-          *  If the %%key%% and %%values%% do not refine to a single function in
 
-          *  the ABI, this will throw.
 
-          */
 
-         getFunction(key, values) {
 
-             return this.#getFunction(key, values || null, true);
 
-         }
 
-         /**
 
-          *  Iterate over all functions, calling %%callback%%, sorted by their name.
 
-          */
 
-         forEachFunction(callback) {
 
-             const names = Array.from(this.#functions.keys());
 
-             names.sort((a, b) => a.localeCompare(b));
 
-             for (let i = 0; i < names.length; i++) {
 
-                 const name = names[i];
 
-                 callback((this.#functions.get(name)), i);
 
-             }
 
-         }
 
-         // Find an event definition by any means necessary (unless it is ambiguous)
 
-         #getEvent(key, values, forceUnique) {
 
-             // EventTopic
 
-             if (isHexString(key)) {
 
-                 const eventTopic = key.toLowerCase();
 
-                 for (const fragment of this.#events.values()) {
 
-                     if (eventTopic === fragment.topicHash) {
 
-                         return fragment;
 
-                     }
 
-                 }
 
-                 return null;
 
-             }
 
-             // It is a bare name, look up the function (will return null if ambiguous)
 
-             if (key.indexOf("(") === -1) {
 
-                 const matching = [];
 
-                 for (const [name, fragment] of this.#events) {
 
-                     if (name.split("(" /* fix:) */)[0] === key) {
 
-                         matching.push(fragment);
 
-                     }
 
-                 }
 
-                 if (values) {
 
-                     // Remove all matches that don't have a compatible length.
 
-                     for (let i = matching.length - 1; i >= 0; i--) {
 
-                         if (matching[i].inputs.length < values.length) {
 
-                             matching.splice(i, 1);
 
-                         }
 
-                     }
 
-                     // Remove all matches that don't match the Typed signature
 
-                     for (let i = matching.length - 1; i >= 0; i--) {
 
-                         const inputs = matching[i].inputs;
 
-                         for (let j = 0; j < values.length; j++) {
 
-                             // Not a typed value
 
-                             if (!Typed.isTyped(values[j])) {
 
-                                 continue;
 
-                             }
 
-                             // Make sure the value type matches the input type
 
-                             if (values[j].type !== inputs[j].baseType) {
 
-                                 matching.splice(i, 1);
 
-                                 break;
 
-                             }
 
-                         }
 
-                     }
 
-                 }
 
-                 if (matching.length === 0) {
 
-                     return null;
 
-                 }
 
-                 if (matching.length > 1 && forceUnique) {
 
-                     const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
 
-                     assertArgument(false, `ambiguous event description (i.e. matches ${matchStr})`, "key", key);
 
-                 }
 
-                 return matching[0];
 
-             }
 
-             // Normalize the signature and lookup the function
 
-             const result = this.#events.get(EventFragment.from(key).format());
 
-             if (result) {
 
-                 return result;
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  Get the event name for %%key%%, which may be a topic hash,
 
-          *  event name or event signature that belongs to the ABI.
 
-          */
 
-         getEventName(key) {
 
-             const fragment = this.#getEvent(key, null, false);
 
-             assertArgument(fragment, "no matching event", "key", key);
 
-             return fragment.name;
 
-         }
 
-         /**
 
-          *  Returns true if %%key%% (an event topic hash, event name or
 
-          *  event signature) is present in the ABI.
 
-          *
 
-          *  In the case of an event name, the name may be ambiguous, so
 
-          *  accessing the [[EventFragment]] may require refinement.
 
-          */
 
-         hasEvent(key) {
 
-             return !!this.#getEvent(key, null, false);
 
-         }
 
-         /**
 
-          *  Get the [[EventFragment]] for %%key%%, which may be a topic hash,
 
-          *  event name or event signature that belongs to the ABI.
 
-          *
 
-          *  If %%values%% is provided, it will use the Typed API to handle
 
-          *  ambiguous cases where multiple events match by name.
 
-          *
 
-          *  If the %%key%% and %%values%% do not refine to a single event in
 
-          *  the ABI, this will throw.
 
-          */
 
-         getEvent(key, values) {
 
-             return this.#getEvent(key, values || null, true);
 
-         }
 
-         /**
 
-          *  Iterate over all events, calling %%callback%%, sorted by their name.
 
-          */
 
-         forEachEvent(callback) {
 
-             const names = Array.from(this.#events.keys());
 
-             names.sort((a, b) => a.localeCompare(b));
 
-             for (let i = 0; i < names.length; i++) {
 
-                 const name = names[i];
 
-                 callback((this.#events.get(name)), i);
 
-             }
 
-         }
 
-         /**
 
-          *  Get the [[ErrorFragment]] for %%key%%, which may be an error
 
-          *  selector, error name or error signature that belongs to the ABI.
 
-          *
 
-          *  If %%values%% is provided, it will use the Typed API to handle
 
-          *  ambiguous cases where multiple errors match by name.
 
-          *
 
-          *  If the %%key%% and %%values%% do not refine to a single error in
 
-          *  the ABI, this will throw.
 
-          */
 
-         getError(key, values) {
 
-             if (isHexString(key)) {
 
-                 const selector = key.toLowerCase();
 
-                 if (BuiltinErrors[selector]) {
 
-                     return ErrorFragment.from(BuiltinErrors[selector].signature);
 
-                 }
 
-                 for (const fragment of this.#errors.values()) {
 
-                     if (selector === fragment.selector) {
 
-                         return fragment;
 
-                     }
 
-                 }
 
-                 return null;
 
-             }
 
-             // It is a bare name, look up the function (will return null if ambiguous)
 
-             if (key.indexOf("(") === -1) {
 
-                 const matching = [];
 
-                 for (const [name, fragment] of this.#errors) {
 
-                     if (name.split("(" /* fix:) */)[0] === key) {
 
-                         matching.push(fragment);
 
-                     }
 
-                 }
 
-                 if (matching.length === 0) {
 
-                     if (key === "Error") {
 
-                         return ErrorFragment.from("error Error(string)");
 
-                     }
 
-                     if (key === "Panic") {
 
-                         return ErrorFragment.from("error Panic(uint256)");
 
-                     }
 
-                     return null;
 
-                 }
 
-                 else if (matching.length > 1) {
 
-                     const matchStr = matching.map((m) => JSON.stringify(m.format())).join(", ");
 
-                     assertArgument(false, `ambiguous error description (i.e. ${matchStr})`, "name", key);
 
-                 }
 
-                 return matching[0];
 
-             }
 
-             // Normalize the signature and lookup the function
 
-             key = ErrorFragment.from(key).format();
 
-             if (key === "Error(string)") {
 
-                 return ErrorFragment.from("error Error(string)");
 
-             }
 
-             if (key === "Panic(uint256)") {
 
-                 return ErrorFragment.from("error Panic(uint256)");
 
-             }
 
-             const result = this.#errors.get(key);
 
-             if (result) {
 
-                 return result;
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  Iterate over all errors, calling %%callback%%, sorted by their name.
 
-          */
 
-         forEachError(callback) {
 
-             const names = Array.from(this.#errors.keys());
 
-             names.sort((a, b) => a.localeCompare(b));
 
-             for (let i = 0; i < names.length; i++) {
 
-                 const name = names[i];
 
-                 callback((this.#errors.get(name)), i);
 
-             }
 
-         }
 
-         // Get the 4-byte selector used by Solidity to identify a function
 
-         /*
 
-     getSelector(fragment: ErrorFragment | FunctionFragment): string {
 
-         if (typeof(fragment) === "string") {
 
-             const matches: Array<Fragment> = [ ];
 
-             try { matches.push(this.getFunction(fragment)); } catch (error) { }
 
-             try { matches.push(this.getError(<string>fragment)); } catch (_) { }
 
-             if (matches.length === 0) {
 
-                 logger.throwArgumentError("unknown fragment", "key", fragment);
 
-             } else if (matches.length > 1) {
 
-                 logger.throwArgumentError("ambiguous fragment matches function and error", "key", fragment);
 
-             }
 
-             fragment = matches[0];
 
-         }
 
-         return dataSlice(id(fragment.format()), 0, 4);
 
-     }
 
-         */
 
-         // Get the 32-byte topic hash used by Solidity to identify an event
 
-         /*
 
-         getEventTopic(fragment: EventFragment): string {
 
-             //if (typeof(fragment) === "string") { fragment = this.getEvent(eventFragment); }
 
-             return id(fragment.format());
 
-         }
 
-         */
 
-         _decodeParams(params, data) {
 
-             return this.#abiCoder.decode(params, data);
 
-         }
 
-         _encodeParams(params, values) {
 
-             return this.#abiCoder.encode(params, values);
 
-         }
 
-         /**
 
-          *  Encodes a ``tx.data`` object for deploying the Contract with
 
-          *  the %%values%% as the constructor arguments.
 
-          */
 
-         encodeDeploy(values) {
 
-             return this._encodeParams(this.deploy.inputs, values || []);
 
-         }
 
-         /**
 
-          *  Decodes the result %%data%% (e.g. from an ``eth_call``) for the
 
-          *  specified error (see [[getError]] for valid values for
 
-          *  %%key%%).
 
-          *
 
-          *  Most developers should prefer the [[parseCallResult]] method instead,
 
-          *  which will automatically detect a ``CALL_EXCEPTION`` and throw the
 
-          *  corresponding error.
 
-          */
 
-         decodeErrorResult(fragment, data) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getError(fragment);
 
-                 assertArgument(f, "unknown error", "fragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             assertArgument(dataSlice(data, 0, 4) === fragment.selector, `data signature does not match error ${fragment.name}.`, "data", data);
 
-             return this._decodeParams(fragment.inputs, dataSlice(data, 4));
 
-         }
 
-         /**
 
-          *  Encodes the transaction revert data for a call result that
 
-          *  reverted from the the Contract with the sepcified %%error%%
 
-          *  (see [[getError]] for valid values for %%fragment%%) with the %%values%%.
 
-          *
 
-          *  This is generally not used by most developers, unless trying to mock
 
-          *  a result from a Contract.
 
-          */
 
-         encodeErrorResult(fragment, values) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getError(fragment);
 
-                 assertArgument(f, "unknown error", "fragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             return concat([
 
-                 fragment.selector,
 
-                 this._encodeParams(fragment.inputs, values || [])
 
-             ]);
 
-         }
 
-         /**
 
-          *  Decodes the %%data%% from a transaction ``tx.data`` for
 
-          *  the function specified (see [[getFunction]] for valid values
 
-          *  for %%fragment%%).
 
-          *
 
-          *  Most developers should prefer the [[parseTransaction]] method
 
-          *  instead, which will automatically detect the fragment.
 
-          */
 
-         decodeFunctionData(fragment, data) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getFunction(fragment);
 
-                 assertArgument(f, "unknown function", "fragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             assertArgument(dataSlice(data, 0, 4) === fragment.selector, `data signature does not match function ${fragment.name}.`, "data", data);
 
-             return this._decodeParams(fragment.inputs, dataSlice(data, 4));
 
-         }
 
-         /**
 
-          *  Encodes the ``tx.data`` for a transaction that calls the function
 
-          *  specified (see [[getFunction]] for valid values for %%fragment%%) with
 
-          *  the %%values%%.
 
-          */
 
-         encodeFunctionData(fragment, values) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getFunction(fragment);
 
-                 assertArgument(f, "unknown function", "fragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             return concat([
 
-                 fragment.selector,
 
-                 this._encodeParams(fragment.inputs, values || [])
 
-             ]);
 
-         }
 
-         /**
 
-          *  Decodes the result %%data%% (e.g. from an ``eth_call``) for the
 
-          *  specified function (see [[getFunction]] for valid values for
 
-          *  %%key%%).
 
-          *
 
-          *  Most developers should prefer the [[parseCallResult]] method instead,
 
-          *  which will automatically detect a ``CALL_EXCEPTION`` and throw the
 
-          *  corresponding error.
 
-          */
 
-         decodeFunctionResult(fragment, data) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getFunction(fragment);
 
-                 assertArgument(f, "unknown function", "fragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             let message = "invalid length for result data";
 
-             const bytes = getBytesCopy(data);
 
-             if ((bytes.length % 32) === 0) {
 
-                 try {
 
-                     return this.#abiCoder.decode(fragment.outputs, bytes);
 
-                 }
 
-                 catch (error) {
 
-                     message = "could not decode result data";
 
-                 }
 
-             }
 
-             // Call returned data with no error, but the data is junk
 
-             assert(false, message, "BAD_DATA", {
 
-                 value: hexlify(bytes),
 
-                 info: { method: fragment.name, signature: fragment.format() }
 
-             });
 
-         }
 
-         makeError(_data, tx) {
 
-             const data = getBytes(_data, "data");
 
-             const error = AbiCoder.getBuiltinCallException("call", tx, data);
 
-             // Not a built-in error; try finding a custom error
 
-             const customPrefix = "execution reverted (unknown custom error)";
 
-             if (error.message.startsWith(customPrefix)) {
 
-                 const selector = hexlify(data.slice(0, 4));
 
-                 const ef = this.getError(selector);
 
-                 if (ef) {
 
-                     try {
 
-                         const args = this.#abiCoder.decode(ef.inputs, data.slice(4));
 
-                         error.revert = {
 
-                             name: ef.name, signature: ef.format(), args
 
-                         };
 
-                         error.reason = error.revert.signature;
 
-                         error.message = `execution reverted: ${error.reason}`;
 
-                     }
 
-                     catch (e) {
 
-                         error.message = `execution reverted (coult not decode custom error)`;
 
-                     }
 
-                 }
 
-             }
 
-             // Add the invocation, if available
 
-             const parsed = this.parseTransaction(tx);
 
-             if (parsed) {
 
-                 error.invocation = {
 
-                     method: parsed.name,
 
-                     signature: parsed.signature,
 
-                     args: parsed.args
 
-                 };
 
-             }
 
-             return error;
 
-         }
 
-         /**
 
-          *  Encodes the result data (e.g. from an ``eth_call``) for the
 
-          *  specified function (see [[getFunction]] for valid values
 
-          *  for %%fragment%%) with %%values%%.
 
-          *
 
-          *  This is generally not used by most developers, unless trying to mock
 
-          *  a result from a Contract.
 
-          */
 
-         encodeFunctionResult(fragment, values) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getFunction(fragment);
 
-                 assertArgument(f, "unknown function", "fragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             return hexlify(this.#abiCoder.encode(fragment.outputs, values || []));
 
-         }
 
-         /*
 
-             spelunk(inputs: Array<ParamType>, values: ReadonlyArray<any>, processfunc: (type: string, value: any) => Promise<any>): Promise<Array<any>> {
 
-                 const promises: Array<Promise<>> = [ ];
 
-                 const process = function(type: ParamType, value: any): any {
 
-                     if (type.baseType === "array") {
 
-                         return descend(type.child
 
-                     }
 
-                     if (type. === "address") {
 
-                     }
 
-                 };
 
-         
 
-                 const descend = function (inputs: Array<ParamType>, values: ReadonlyArray<any>) {
 
-                     if (inputs.length !== values.length) { throw new Error("length mismatch"); }
 
-                     
 
-                 };
 
-         
 
-                 const result: Array<any> = [ ];
 
-                 values.forEach((value, index) => {
 
-                     if (value == null) {
 
-                         topics.push(null);
 
-                     } else if (param.baseType === "array" || param.baseType === "tuple") {
 
-                         logger.throwArgumentError("filtering with tuples or arrays not supported", ("contract." + param.name), value);
 
-                     } else if (Array.isArray(value)) {
 
-                         topics.push(value.map((value) => encodeTopic(param, value)));
 
-                     } else {
 
-                         topics.push(encodeTopic(param, value));
 
-                     }
 
-                 });
 
-             }
 
-         */
 
-         // Create the filter for the event with search criteria (e.g. for eth_filterLog)
 
-         encodeFilterTopics(fragment, values) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getEvent(fragment);
 
-                 assertArgument(f, "unknown event", "eventFragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             assert(values.length <= fragment.inputs.length, `too many arguments for ${fragment.format()}`, "UNEXPECTED_ARGUMENT", { count: values.length, expectedCount: fragment.inputs.length });
 
-             const topics = [];
 
-             if (!fragment.anonymous) {
 
-                 topics.push(fragment.topicHash);
 
-             }
 
-             // @TODO: Use the coders for this; to properly support tuples, etc.
 
-             const encodeTopic = (param, value) => {
 
-                 if (param.type === "string") {
 
-                     return id(value);
 
-                 }
 
-                 else if (param.type === "bytes") {
 
-                     return keccak256(hexlify(value));
 
-                 }
 
-                 if (param.type === "bool" && typeof (value) === "boolean") {
 
-                     value = (value ? "0x01" : "0x00");
 
-                 }
 
-                 else if (param.type.match(/^u?int/)) {
 
-                     value = toBeHex(value); // @TODO: Should this toTwos??
 
-                 }
 
-                 else if (param.type.match(/^bytes/)) {
 
-                     value = zeroPadBytes(value, 32);
 
-                 }
 
-                 else if (param.type === "address") {
 
-                     // Check addresses are valid
 
-                     this.#abiCoder.encode(["address"], [value]);
 
-                 }
 
-                 return zeroPadValue(hexlify(value), 32);
 
-             };
 
-             values.forEach((value, index) => {
 
-                 const param = fragment.inputs[index];
 
-                 if (!param.indexed) {
 
-                     assertArgument(value == null, "cannot filter non-indexed parameters; must be null", ("contract." + param.name), value);
 
-                     return;
 
-                 }
 
-                 if (value == null) {
 
-                     topics.push(null);
 
-                 }
 
-                 else if (param.baseType === "array" || param.baseType === "tuple") {
 
-                     assertArgument(false, "filtering with tuples or arrays not supported", ("contract." + param.name), value);
 
-                 }
 
-                 else if (Array.isArray(value)) {
 
-                     topics.push(value.map((value) => encodeTopic(param, value)));
 
-                 }
 
-                 else {
 
-                     topics.push(encodeTopic(param, value));
 
-                 }
 
-             });
 
-             // Trim off trailing nulls
 
-             while (topics.length && topics[topics.length - 1] === null) {
 
-                 topics.pop();
 
-             }
 
-             return topics;
 
-         }
 
-         encodeEventLog(fragment, values) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getEvent(fragment);
 
-                 assertArgument(f, "unknown event", "eventFragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             const topics = [];
 
-             const dataTypes = [];
 
-             const dataValues = [];
 
-             if (!fragment.anonymous) {
 
-                 topics.push(fragment.topicHash);
 
-             }
 
-             assertArgument(values.length === fragment.inputs.length, "event arguments/values mismatch", "values", values);
 
-             fragment.inputs.forEach((param, index) => {
 
-                 const value = values[index];
 
-                 if (param.indexed) {
 
-                     if (param.type === "string") {
 
-                         topics.push(id(value));
 
-                     }
 
-                     else if (param.type === "bytes") {
 
-                         topics.push(keccak256(value));
 
-                     }
 
-                     else if (param.baseType === "tuple" || param.baseType === "array") {
 
-                         // @TODO
 
-                         throw new Error("not implemented");
 
-                     }
 
-                     else {
 
-                         topics.push(this.#abiCoder.encode([param.type], [value]));
 
-                     }
 
-                 }
 
-                 else {
 
-                     dataTypes.push(param);
 
-                     dataValues.push(value);
 
-                 }
 
-             });
 
-             return {
 
-                 data: this.#abiCoder.encode(dataTypes, dataValues),
 
-                 topics: topics
 
-             };
 
-         }
 
-         // Decode a filter for the event and the search criteria
 
-         decodeEventLog(fragment, data, topics) {
 
-             if (typeof (fragment) === "string") {
 
-                 const f = this.getEvent(fragment);
 
-                 assertArgument(f, "unknown event", "eventFragment", fragment);
 
-                 fragment = f;
 
-             }
 
-             if (topics != null && !fragment.anonymous) {
 
-                 const eventTopic = fragment.topicHash;
 
-                 assertArgument(isHexString(topics[0], 32) && topics[0].toLowerCase() === eventTopic, "fragment/topic mismatch", "topics[0]", topics[0]);
 
-                 topics = topics.slice(1);
 
-             }
 
-             const indexed = [];
 
-             const nonIndexed = [];
 
-             const dynamic = [];
 
-             fragment.inputs.forEach((param, index) => {
 
-                 if (param.indexed) {
 
-                     if (param.type === "string" || param.type === "bytes" || param.baseType === "tuple" || param.baseType === "array") {
 
-                         indexed.push(ParamType.from({ type: "bytes32", name: param.name }));
 
-                         dynamic.push(true);
 
-                     }
 
-                     else {
 
-                         indexed.push(param);
 
-                         dynamic.push(false);
 
-                     }
 
-                 }
 
-                 else {
 
-                     nonIndexed.push(param);
 
-                     dynamic.push(false);
 
-                 }
 
-             });
 
-             const resultIndexed = (topics != null) ? this.#abiCoder.decode(indexed, concat(topics)) : null;
 
-             const resultNonIndexed = this.#abiCoder.decode(nonIndexed, data, true);
 
-             //const result: (Array<any> & { [ key: string ]: any }) = [ ];
 
-             const values = [];
 
-             const keys = [];
 
-             let nonIndexedIndex = 0, indexedIndex = 0;
 
-             fragment.inputs.forEach((param, index) => {
 
-                 let value = null;
 
-                 if (param.indexed) {
 
-                     if (resultIndexed == null) {
 
-                         value = new Indexed(null);
 
-                     }
 
-                     else if (dynamic[index]) {
 
-                         value = new Indexed(resultIndexed[indexedIndex++]);
 
-                     }
 
-                     else {
 
-                         try {
 
-                             value = resultIndexed[indexedIndex++];
 
-                         }
 
-                         catch (error) {
 
-                             value = error;
 
-                         }
 
-                     }
 
-                 }
 
-                 else {
 
-                     try {
 
-                         value = resultNonIndexed[nonIndexedIndex++];
 
-                     }
 
-                     catch (error) {
 
-                         value = error;
 
-                     }
 
-                 }
 
-                 values.push(value);
 
-                 keys.push(param.name || null);
 
-             });
 
-             return Result.fromItems(values, keys);
 
-         }
 
-         /**
 
-          *  Parses a transaction, finding the matching function and extracts
 
-          *  the parameter values along with other useful function details.
 
-          *
 
-          *  If the matching function cannot be found, return null.
 
-          */
 
-         parseTransaction(tx) {
 
-             const data = getBytes(tx.data, "tx.data");
 
-             const value = getBigInt((tx.value != null) ? tx.value : 0, "tx.value");
 
-             const fragment = this.getFunction(hexlify(data.slice(0, 4)));
 
-             if (!fragment) {
 
-                 return null;
 
-             }
 
-             const args = this.#abiCoder.decode(fragment.inputs, data.slice(4));
 
-             return new TransactionDescription(fragment, fragment.selector, args, value);
 
-         }
 
-         parseCallResult(data) {
 
-             throw new Error("@TODO");
 
-         }
 
-         /**
 
-          *  Parses a receipt log, finding the matching event and extracts
 
-          *  the parameter values along with other useful event details.
 
-          *
 
-          *  If the matching event cannot be found, returns null.
 
-          */
 
-         parseLog(log) {
 
-             const fragment = this.getEvent(log.topics[0]);
 
-             if (!fragment || fragment.anonymous) {
 
-                 return null;
 
-             }
 
-             // @TODO: If anonymous, and the only method, and the input count matches, should we parse?
 
-             //        Probably not, because just because it is the only event in the ABI does
 
-             //        not mean we have the full ABI; maybe just a fragment?
 
-             return new LogDescription(fragment, fragment.topicHash, this.decodeEventLog(fragment, log.data, log.topics));
 
-         }
 
-         /**
 
-          *  Parses a revert data, finding the matching error and extracts
 
-          *  the parameter values along with other useful error details.
 
-          *
 
-          *  If the matching error cannot be found, returns null.
 
-          */
 
-         parseError(data) {
 
-             const hexData = hexlify(data);
 
-             const fragment = this.getError(dataSlice(hexData, 0, 4));
 
-             if (!fragment) {
 
-                 return null;
 
-             }
 
-             const args = this.#abiCoder.decode(fragment.inputs, dataSlice(hexData, 4));
 
-             return new ErrorDescription(fragment, fragment.selector, args);
 
-         }
 
-         /**
 
-          *  Creates a new [[Interface]] from the ABI %%value%%.
 
-          *
 
-          *  The %%value%% may be provided as an existing [[Interface]] object,
 
-          *  a JSON-encoded ABI or any Human-Readable ABI format.
 
-          */
 
-         static from(value) {
 
-             // Already an Interface, which is immutable
 
-             if (value instanceof Interface) {
 
-                 return value;
 
-             }
 
-             // JSON
 
-             if (typeof (value) === "string") {
 
-                 return new Interface(JSON.parse(value));
 
-             }
 
-             // An Interface; possibly from another v6 instance
 
-             if (typeof (value.formatJson) === "function") {
 
-                 return new Interface(value.formatJson());
 
-             }
 
-             // A legacy Interface; from an older version
 
-             if (typeof (value.format) === "function") {
 
-                 return new Interface(value.format("json"));
 
-             }
 
-             // Array of fragments
 
-             return new Interface(value);
 
-         }
 
-     }
 
-     //import { resolveAddress } from "@ethersproject/address";
 
-     const BN_0$2 = BigInt(0);
 
-     // -----------------------
 
-     function getValue(value) {
 
-         if (value == null) {
 
-             return null;
 
-         }
 
-         return value;
 
-     }
 
-     function toJson(value) {
 
-         if (value == null) {
 
-             return null;
 
-         }
 
-         return value.toString();
 
-     }
 
-     // @TODO? <T extends FeeData = { }> implements Required<T>
 
-     /**
 
-      *  A **FeeData** wraps all the fee-related values associated with
 
-      *  the network.
 
-      */
 
-     class FeeData {
 
-         /**
 
-          *  The gas price for legacy networks.
 
-          */
 
-         gasPrice;
 
-         /**
 
-          *  The maximum fee to pay per gas.
 
-          *
 
-          *  The base fee per gas is defined by the network and based on
 
-          *  congestion, increasing the cost during times of heavy load
 
-          *  and lowering when less busy.
 
-          *
 
-          *  The actual fee per gas will be the base fee for the block
 
-          *  and the priority fee, up to the max fee per gas.
 
-          *
 
-          *  This will be ``null`` on legacy networks (i.e. [pre-EIP-1559](link-eip-1559))
 
-          */
 
-         maxFeePerGas;
 
-         /**
 
-          *  The additional amout to pay per gas to encourage a validator
 
-          *  to include the transaction.
 
-          *
 
-          *  The purpose of this is to compensate the validator for the
 
-          *  adjusted risk for including a given transaction.
 
-          *
 
-          *  This will be ``null`` on legacy networks (i.e. [pre-EIP-1559](link-eip-1559))
 
-          */
 
-         maxPriorityFeePerGas;
 
-         /**
 
-          *  Creates a new FeeData for %%gasPrice%%, %%maxFeePerGas%% and
 
-          *  %%maxPriorityFeePerGas%%.
 
-          */
 
-         constructor(gasPrice, maxFeePerGas, maxPriorityFeePerGas) {
 
-             defineProperties(this, {
 
-                 gasPrice: getValue(gasPrice),
 
-                 maxFeePerGas: getValue(maxFeePerGas),
 
-                 maxPriorityFeePerGas: getValue(maxPriorityFeePerGas)
 
-             });
 
-         }
 
-         /**
 
-          *  Returns a JSON-friendly value.
 
-          */
 
-         toJSON() {
 
-             const { gasPrice, maxFeePerGas, maxPriorityFeePerGas } = this;
 
-             return {
 
-                 _type: "FeeData",
 
-                 gasPrice: toJson(gasPrice),
 
-                 maxFeePerGas: toJson(maxFeePerGas),
 
-                 maxPriorityFeePerGas: toJson(maxPriorityFeePerGas),
 
-             };
 
-         }
 
-     }
 
-     /**
 
-      *  Returns a copy of %%req%% with all properties coerced to their strict
 
-      *  types.
 
-      */
 
-     function copyRequest(req) {
 
-         const result = {};
 
-         // These could be addresses, ENS names or Addressables
 
-         if (req.to) {
 
-             result.to = req.to;
 
-         }
 
-         if (req.from) {
 
-             result.from = req.from;
 
-         }
 
-         if (req.data) {
 
-             result.data = hexlify(req.data);
 
-         }
 
-         const bigIntKeys = "chainId,gasLimit,gasPrice,maxFeePerBlobGas,maxFeePerGas,maxPriorityFeePerGas,value".split(/,/);
 
-         for (const key of bigIntKeys) {
 
-             if (!(key in req) || req[key] == null) {
 
-                 continue;
 
-             }
 
-             result[key] = getBigInt(req[key], `request.${key}`);
 
-         }
 
-         const numberKeys = "type,nonce".split(/,/);
 
-         for (const key of numberKeys) {
 
-             if (!(key in req) || req[key] == null) {
 
-                 continue;
 
-             }
 
-             result[key] = getNumber(req[key], `request.${key}`);
 
-         }
 
-         if (req.accessList) {
 
-             result.accessList = accessListify(req.accessList);
 
-         }
 
-         if ("blockTag" in req) {
 
-             result.blockTag = req.blockTag;
 
-         }
 
-         if ("enableCcipRead" in req) {
 
-             result.enableCcipRead = !!req.enableCcipRead;
 
-         }
 
-         if ("customData" in req) {
 
-             result.customData = req.customData;
 
-         }
 
-         if ("blobVersionedHashes" in req && req.blobVersionedHashes) {
 
-             result.blobVersionedHashes = req.blobVersionedHashes.slice();
 
-         }
 
-         if ("kzg" in req) {
 
-             result.kzg = req.kzg;
 
-         }
 
-         if ("blobs" in req && req.blobs) {
 
-             result.blobs = req.blobs.map((b) => {
 
-                 if (isBytesLike(b)) {
 
-                     return hexlify(b);
 
-                 }
 
-                 return Object.assign({}, b);
 
-             });
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  A **Block** represents the data associated with a full block on
 
-      *  Ethereum.
 
-      */
 
-     class Block {
 
-         /**
 
-          *  The provider connected to the block used to fetch additional details
 
-          *  if necessary.
 
-          */
 
-         provider;
 
-         /**
 
-          *  The block number, sometimes called the block height. This is a
 
-          *  sequential number that is one higher than the parent block.
 
-          */
 
-         number;
 
-         /**
 
-          *  The block hash.
 
-          *
 
-          *  This hash includes all properties, so can be safely used to identify
 
-          *  an exact set of block properties.
 
-          */
 
-         hash;
 
-         /**
 
-          *  The timestamp for this block, which is the number of seconds since
 
-          *  epoch that this block was included.
 
-          */
 
-         timestamp;
 
-         /**
 
-          *  The block hash of the parent block.
 
-          */
 
-         parentHash;
 
-         /**
 
-          *  The hash tree root of the parent beacon block for the given
 
-          *  execution block. See [[link-eip-4788]].
 
-          */
 
-         parentBeaconBlockRoot;
 
-         /**
 
-          *  The nonce.
 
-          *
 
-          *  On legacy networks, this is the random number inserted which
 
-          *  permitted the difficulty target to be reached.
 
-          */
 
-         nonce;
 
-         /**
 
-          *  The difficulty target.
 
-          *
 
-          *  On legacy networks, this is the proof-of-work target required
 
-          *  for a block to meet the protocol rules to be included.
 
-          *
 
-          *  On modern networks, this is a random number arrived at using
 
-          *  randao.  @TODO: Find links?
 
-          */
 
-         difficulty;
 
-         /**
 
-          *  The total gas limit for this block.
 
-          */
 
-         gasLimit;
 
-         /**
 
-          *  The total gas used in this block.
 
-          */
 
-         gasUsed;
 
-         /**
 
-          *  The root hash for the global state after applying changes
 
-          *  in this block.
 
-          */
 
-         stateRoot;
 
-         /**
 
-          *  The hash of the transaction receipts trie.
 
-          */
 
-         receiptsRoot;
 
-         /**
 
-          *  The total amount of blob gas consumed by the transactions
 
-          *  within the block. See [[link-eip-4844]].
 
-          */
 
-         blobGasUsed;
 
-         /**
 
-          *  The running total of blob gas consumed in excess of the
 
-          *  target, prior to the block. See [[link-eip-4844]].
 
-          */
 
-         excessBlobGas;
 
-         /**
 
-          *  The miner coinbase address, wihch receives any subsidies for
 
-          *  including this block.
 
-          */
 
-         miner;
 
-         /**
 
-          *  The latest RANDAO mix of the post beacon state of
 
-          *  the previous block.
 
-          */
 
-         prevRandao;
 
-         /**
 
-          *  Any extra data the validator wished to include.
 
-          */
 
-         extraData;
 
-         /**
 
-          *  The base fee per gas that all transactions in this block were
 
-          *  charged.
 
-          *
 
-          *  This adjusts after each block, depending on how congested the network
 
-          *  is.
 
-          */
 
-         baseFeePerGas;
 
-         #transactions;
 
-         /**
 
-          *  Create a new **Block** object.
 
-          *
 
-          *  This should generally not be necessary as the unless implementing a
 
-          *  low-level library.
 
-          */
 
-         constructor(block, provider) {
 
-             this.#transactions = block.transactions.map((tx) => {
 
-                 if (typeof (tx) !== "string") {
 
-                     return new TransactionResponse(tx, provider);
 
-                 }
 
-                 return tx;
 
-             });
 
-             defineProperties(this, {
 
-                 provider,
 
-                 hash: getValue(block.hash),
 
-                 number: block.number,
 
-                 timestamp: block.timestamp,
 
-                 parentHash: block.parentHash,
 
-                 parentBeaconBlockRoot: block.parentBeaconBlockRoot,
 
-                 nonce: block.nonce,
 
-                 difficulty: block.difficulty,
 
-                 gasLimit: block.gasLimit,
 
-                 gasUsed: block.gasUsed,
 
-                 blobGasUsed: block.blobGasUsed,
 
-                 excessBlobGas: block.excessBlobGas,
 
-                 miner: block.miner,
 
-                 prevRandao: getValue(block.prevRandao),
 
-                 extraData: block.extraData,
 
-                 baseFeePerGas: getValue(block.baseFeePerGas),
 
-                 stateRoot: block.stateRoot,
 
-                 receiptsRoot: block.receiptsRoot,
 
-             });
 
-         }
 
-         /**
 
-          *  Returns the list of transaction hashes, in the order
 
-          *  they were executed within the block.
 
-          */
 
-         get transactions() {
 
-             return this.#transactions.map((tx) => {
 
-                 if (typeof (tx) === "string") {
 
-                     return tx;
 
-                 }
 
-                 return tx.hash;
 
-             });
 
-         }
 
-         /**
 
-          *  Returns the complete transactions, in the order they
 
-          *  were executed within the block.
 
-          *
 
-          *  This is only available for blocks which prefetched
 
-          *  transactions, by passing ``true`` to %%prefetchTxs%%
 
-          *  into [[Provider-getBlock]].
 
-          */
 
-         get prefetchedTransactions() {
 
-             const txs = this.#transactions.slice();
 
-             // Doesn't matter...
 
-             if (txs.length === 0) {
 
-                 return [];
 
-             }
 
-             // Make sure we prefetched the transactions
 
-             assert(typeof (txs[0]) === "object", "transactions were not prefetched with block request", "UNSUPPORTED_OPERATION", {
 
-                 operation: "transactionResponses()"
 
-             });
 
-             return txs;
 
-         }
 
-         /**
 
-          *  Returns a JSON-friendly value.
 
-          */
 
-         toJSON() {
 
-             const { baseFeePerGas, difficulty, extraData, gasLimit, gasUsed, hash, miner, prevRandao, nonce, number, parentHash, parentBeaconBlockRoot, stateRoot, receiptsRoot, timestamp, transactions } = this;
 
-             return {
 
-                 _type: "Block",
 
-                 baseFeePerGas: toJson(baseFeePerGas),
 
-                 difficulty: toJson(difficulty),
 
-                 extraData,
 
-                 gasLimit: toJson(gasLimit),
 
-                 gasUsed: toJson(gasUsed),
 
-                 blobGasUsed: toJson(this.blobGasUsed),
 
-                 excessBlobGas: toJson(this.excessBlobGas),
 
-                 hash, miner, prevRandao, nonce, number, parentHash, timestamp,
 
-                 parentBeaconBlockRoot, stateRoot, receiptsRoot,
 
-                 transactions,
 
-             };
 
-         }
 
-         [Symbol.iterator]() {
 
-             let index = 0;
 
-             const txs = this.transactions;
 
-             return {
 
-                 next: () => {
 
-                     if (index < this.length) {
 
-                         return {
 
-                             value: txs[index++], done: false
 
-                         };
 
-                     }
 
-                     return { value: undefined, done: true };
 
-                 }
 
-             };
 
-         }
 
-         /**
 
-          *  The number of transactions in this block.
 
-          */
 
-         get length() { return this.#transactions.length; }
 
-         /**
 
-          *  The [[link-js-date]] this block was included at.
 
-          */
 
-         get date() {
 
-             if (this.timestamp == null) {
 
-                 return null;
 
-             }
 
-             return new Date(this.timestamp * 1000);
 
-         }
 
-         /**
 
-          *  Get the transaction at %%indexe%% within this block.
 
-          */
 
-         async getTransaction(indexOrHash) {
 
-             // Find the internal value by its index or hash
 
-             let tx = undefined;
 
-             if (typeof (indexOrHash) === "number") {
 
-                 tx = this.#transactions[indexOrHash];
 
-             }
 
-             else {
 
-                 const hash = indexOrHash.toLowerCase();
 
-                 for (const v of this.#transactions) {
 
-                     if (typeof (v) === "string") {
 
-                         if (v !== hash) {
 
-                             continue;
 
-                         }
 
-                         tx = v;
 
-                         break;
 
-                     }
 
-                     else {
 
-                         if (v.hash !== hash) {
 
-                             continue;
 
-                         }
 
-                         tx = v;
 
-                         break;
 
-                     }
 
-                 }
 
-             }
 
-             if (tx == null) {
 
-                 throw new Error("no such tx");
 
-             }
 
-             if (typeof (tx) === "string") {
 
-                 return (await this.provider.getTransaction(tx));
 
-             }
 
-             else {
 
-                 return tx;
 
-             }
 
-         }
 
-         /**
 
-          *  If a **Block** was fetched with a request to include the transactions
 
-          *  this will allow synchronous access to those transactions.
 
-          *
 
-          *  If the transactions were not prefetched, this will throw.
 
-          */
 
-         getPrefetchedTransaction(indexOrHash) {
 
-             const txs = this.prefetchedTransactions;
 
-             if (typeof (indexOrHash) === "number") {
 
-                 return txs[indexOrHash];
 
-             }
 
-             indexOrHash = indexOrHash.toLowerCase();
 
-             for (const tx of txs) {
 
-                 if (tx.hash === indexOrHash) {
 
-                     return tx;
 
-                 }
 
-             }
 
-             assertArgument(false, "no matching transaction", "indexOrHash", indexOrHash);
 
-         }
 
-         /**
 
-          *  Returns true if this block been mined. This provides a type guard
 
-          *  for all properties on a [[MinedBlock]].
 
-          */
 
-         isMined() { return !!this.hash; }
 
-         /**
 
-          *  Returns true if this block is an [[link-eip-2930]] block.
 
-          */
 
-         isLondon() {
 
-             return !!this.baseFeePerGas;
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         orphanedEvent() {
 
-             if (!this.isMined()) {
 
-                 throw new Error("");
 
-             }
 
-             return createOrphanedBlockFilter(this);
 
-         }
 
-     }
 
-     //////////////////////
 
-     // Log
 
-     /**
 
-      *  A **Log** in Ethereum represents an event that has been included in a
 
-      *  transaction using the ``LOG*`` opcodes, which are most commonly used by
 
-      *  Solidity's emit for announcing events.
 
-      */
 
-     class Log {
 
-         /**
 
-          *  The provider connected to the log used to fetch additional details
 
-          *  if necessary.
 
-          */
 
-         provider;
 
-         /**
 
-          *  The transaction hash of the transaction this log occurred in. Use the
 
-          *  [[Log-getTransaction]] to get the [[TransactionResponse]].
 
-          */
 
-         transactionHash;
 
-         /**
 
-          *  The block hash of the block this log occurred in. Use the
 
-          *  [[Log-getBlock]] to get the [[Block]].
 
-          */
 
-         blockHash;
 
-         /**
 
-          *  The block number of the block this log occurred in. It is preferred
 
-          *  to use the [[Block-hash]] when fetching the related [[Block]],
 
-          *  since in the case of an orphaned block, the block at that height may
 
-          *  have changed.
 
-          */
 
-         blockNumber;
 
-         /**
 
-          *  If the **Log** represents a block that was removed due to an orphaned
 
-          *  block, this will be true.
 
-          *
 
-          *  This can only happen within an orphan event listener.
 
-          */
 
-         removed;
 
-         /**
 
-          *  The address of the contract that emitted this log.
 
-          */
 
-         address;
 
-         /**
 
-          *  The data included in this log when it was emitted.
 
-          */
 
-         data;
 
-         /**
 
-          *  The indexed topics included in this log when it was emitted.
 
-          *
 
-          *  All topics are included in the bloom filters, so they can be
 
-          *  efficiently filtered using the [[Provider-getLogs]] method.
 
-          */
 
-         topics;
 
-         /**
 
-          *  The index within the block this log occurred at. This is generally
 
-          *  not useful to developers, but can be used with the various roots
 
-          *  to proof inclusion within a block.
 
-          */
 
-         index;
 
-         /**
 
-          *  The index within the transaction of this log.
 
-          */
 
-         transactionIndex;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(log, provider) {
 
-             this.provider = provider;
 
-             const topics = Object.freeze(log.topics.slice());
 
-             defineProperties(this, {
 
-                 transactionHash: log.transactionHash,
 
-                 blockHash: log.blockHash,
 
-                 blockNumber: log.blockNumber,
 
-                 removed: log.removed,
 
-                 address: log.address,
 
-                 data: log.data,
 
-                 topics,
 
-                 index: log.index,
 
-                 transactionIndex: log.transactionIndex,
 
-             });
 
-         }
 
-         /**
 
-          *  Returns a JSON-compatible object.
 
-          */
 
-         toJSON() {
 
-             const { address, blockHash, blockNumber, data, index, removed, topics, transactionHash, transactionIndex } = this;
 
-             return {
 
-                 _type: "log",
 
-                 address, blockHash, blockNumber, data, index,
 
-                 removed, topics, transactionHash, transactionIndex
 
-             };
 
-         }
 
-         /**
 
-          *  Returns the block that this log occurred in.
 
-          */
 
-         async getBlock() {
 
-             const block = await this.provider.getBlock(this.blockHash);
 
-             assert(!!block, "failed to find transaction", "UNKNOWN_ERROR", {});
 
-             return block;
 
-         }
 
-         /**
 
-          *  Returns the transaction that this log occurred in.
 
-          */
 
-         async getTransaction() {
 
-             const tx = await this.provider.getTransaction(this.transactionHash);
 
-             assert(!!tx, "failed to find transaction", "UNKNOWN_ERROR", {});
 
-             return tx;
 
-         }
 
-         /**
 
-          *  Returns the transaction receipt fot the transaction that this
 
-          *  log occurred in.
 
-          */
 
-         async getTransactionReceipt() {
 
-             const receipt = await this.provider.getTransactionReceipt(this.transactionHash);
 
-             assert(!!receipt, "failed to find transaction receipt", "UNKNOWN_ERROR", {});
 
-             return receipt;
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         removedEvent() {
 
-             return createRemovedLogFilter(this);
 
-         }
 
-     }
 
-     //////////////////////
 
-     // Transaction Receipt
 
-     /*
 
-     export interface LegacyTransactionReceipt {
 
-         byzantium: false;
 
-         status: null;
 
-         root: string;
 
-     }
 
-     export interface ByzantiumTransactionReceipt {
 
-         byzantium: true;
 
-         status: number;
 
-         root: null;
 
-     }
 
-     */
 
-     /**
 
-      *  A **TransactionReceipt** includes additional information about a
 
-      *  transaction that is only available after it has been mined.
 
-      */
 
-     class TransactionReceipt {
 
-         /**
 
-          *  The provider connected to the log used to fetch additional details
 
-          *  if necessary.
 
-          */
 
-         provider;
 
-         /**
 
-          *  The address the transaction was sent to.
 
-          */
 
-         to;
 
-         /**
 
-          *  The sender of the transaction.
 
-          */
 
-         from;
 
-         /**
 
-          *  The address of the contract if the transaction was directly
 
-          *  responsible for deploying one.
 
-          *
 
-          *  This is non-null **only** if the ``to`` is empty and the ``data``
 
-          *  was successfully executed as initcode.
 
-          */
 
-         contractAddress;
 
-         /**
 
-          *  The transaction hash.
 
-          */
 
-         hash;
 
-         /**
 
-          *  The index of this transaction within the block transactions.
 
-          */
 
-         index;
 
-         /**
 
-          *  The block hash of the [[Block]] this transaction was included in.
 
-          */
 
-         blockHash;
 
-         /**
 
-          *  The block number of the [[Block]] this transaction was included in.
 
-          */
 
-         blockNumber;
 
-         /**
 
-          *  The bloom filter bytes that represent all logs that occurred within
 
-          *  this transaction. This is generally not useful for most developers,
 
-          *  but can be used to validate the included logs.
 
-          */
 
-         logsBloom;
 
-         /**
 
-          *  The actual amount of gas used by this transaction.
 
-          *
 
-          *  When creating a transaction, the amount of gas that will be used can
 
-          *  only be approximated, but the sender must pay the gas fee for the
 
-          *  entire gas limit. After the transaction, the difference is refunded.
 
-          */
 
-         gasUsed;
 
-         /**
 
-          *  The gas used for BLObs. See [[link-eip-4844]].
 
-          */
 
-         blobGasUsed;
 
-         /**
 
-          *  The amount of gas used by all transactions within the block for this
 
-          *  and all transactions with a lower ``index``.
 
-          *
 
-          *  This is generally not useful for developers but can be used to
 
-          *  validate certain aspects of execution.
 
-          */
 
-         cumulativeGasUsed;
 
-         /**
 
-          *  The actual gas price used during execution.
 
-          *
 
-          *  Due to the complexity of [[link-eip-1559]] this value can only
 
-          *  be caluclated after the transaction has been mined, snce the base
 
-          *  fee is protocol-enforced.
 
-          */
 
-         gasPrice;
 
-         /**
 
-          *  The price paid per BLOB in gas. See [[link-eip-4844]].
 
-          */
 
-         blobGasPrice;
 
-         /**
 
-          *  The [[link-eip-2718]] transaction type.
 
-          */
 
-         type;
 
-         //readonly byzantium!: boolean;
 
-         /**
 
-          *  The status of this transaction, indicating success (i.e. ``1``) or
 
-          *  a revert (i.e. ``0``).
 
-          *
 
-          *  This is available in post-byzantium blocks, but some backends may
 
-          *  backfill this value.
 
-          */
 
-         status;
 
-         /**
 
-          *  The root hash of this transaction.
 
-          *
 
-          *  This is no present and was only included in pre-byzantium blocks, but
 
-          *  could be used to validate certain parts of the receipt.
 
-          */
 
-         root;
 
-         #logs;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(tx, provider) {
 
-             this.#logs = Object.freeze(tx.logs.map((log) => {
 
-                 return new Log(log, provider);
 
-             }));
 
-             let gasPrice = BN_0$2;
 
-             if (tx.effectiveGasPrice != null) {
 
-                 gasPrice = tx.effectiveGasPrice;
 
-             }
 
-             else if (tx.gasPrice != null) {
 
-                 gasPrice = tx.gasPrice;
 
-             }
 
-             defineProperties(this, {
 
-                 provider,
 
-                 to: tx.to,
 
-                 from: tx.from,
 
-                 contractAddress: tx.contractAddress,
 
-                 hash: tx.hash,
 
-                 index: tx.index,
 
-                 blockHash: tx.blockHash,
 
-                 blockNumber: tx.blockNumber,
 
-                 logsBloom: tx.logsBloom,
 
-                 gasUsed: tx.gasUsed,
 
-                 cumulativeGasUsed: tx.cumulativeGasUsed,
 
-                 blobGasUsed: tx.blobGasUsed,
 
-                 gasPrice,
 
-                 blobGasPrice: tx.blobGasPrice,
 
-                 type: tx.type,
 
-                 //byzantium: tx.byzantium,
 
-                 status: tx.status,
 
-                 root: tx.root
 
-             });
 
-         }
 
-         /**
 
-          *  The logs for this transaction.
 
-          */
 
-         get logs() { return this.#logs; }
 
-         /**
 
-          *  Returns a JSON-compatible representation.
 
-          */
 
-         toJSON() {
 
-             const { to, from, contractAddress, hash, index, blockHash, blockNumber, logsBloom, logs, //byzantium, 
 
-             status, root } = this;
 
-             return {
 
-                 _type: "TransactionReceipt",
 
-                 blockHash, blockNumber,
 
-                 //byzantium, 
 
-                 contractAddress,
 
-                 cumulativeGasUsed: toJson(this.cumulativeGasUsed),
 
-                 from,
 
-                 gasPrice: toJson(this.gasPrice),
 
-                 blobGasUsed: toJson(this.blobGasUsed),
 
-                 blobGasPrice: toJson(this.blobGasPrice),
 
-                 gasUsed: toJson(this.gasUsed),
 
-                 hash, index, logs, logsBloom, root, status, to
 
-             };
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         get length() { return this.logs.length; }
 
-         [Symbol.iterator]() {
 
-             let index = 0;
 
-             return {
 
-                 next: () => {
 
-                     if (index < this.length) {
 
-                         return { value: this.logs[index++], done: false };
 
-                     }
 
-                     return { value: undefined, done: true };
 
-                 }
 
-             };
 
-         }
 
-         /**
 
-          *  The total fee for this transaction, in wei.
 
-          */
 
-         get fee() {
 
-             return this.gasUsed * this.gasPrice;
 
-         }
 
-         /**
 
-          *  Resolves to the block this transaction occurred in.
 
-          */
 
-         async getBlock() {
 
-             const block = await this.provider.getBlock(this.blockHash);
 
-             if (block == null) {
 
-                 throw new Error("TODO");
 
-             }
 
-             return block;
 
-         }
 
-         /**
 
-          *  Resolves to the transaction this transaction occurred in.
 
-          */
 
-         async getTransaction() {
 
-             const tx = await this.provider.getTransaction(this.hash);
 
-             if (tx == null) {
 
-                 throw new Error("TODO");
 
-             }
 
-             return tx;
 
-         }
 
-         /**
 
-          *  Resolves to the return value of the execution of this transaction.
 
-          *
 
-          *  Support for this feature is limited, as it requires an archive node
 
-          *  with the ``debug_`` or ``trace_`` API enabled.
 
-          */
 
-         async getResult() {
 
-             return (await this.provider.getTransactionResult(this.hash));
 
-         }
 
-         /**
 
-          *  Resolves to the number of confirmations this transaction has.
 
-          */
 
-         async confirmations() {
 
-             return (await this.provider.getBlockNumber()) - this.blockNumber + 1;
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         removedEvent() {
 
-             return createRemovedTransactionFilter(this);
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         reorderedEvent(other) {
 
-             assert(!other || other.isMined(), "unmined 'other' transction cannot be orphaned", "UNSUPPORTED_OPERATION", { operation: "reorderedEvent(other)" });
 
-             return createReorderedTransactionFilter(this, other);
 
-         }
 
-     }
 
-     /**
 
-      *  A **TransactionResponse** includes all properties about a transaction
 
-      *  that was sent to the network, which may or may not be included in a
 
-      *  block.
 
-      *
 
-      *  The [[TransactionResponse-isMined]] can be used to check if the
 
-      *  transaction has been mined as well as type guard that the otherwise
 
-      *  possibly ``null`` properties are defined.
 
-      */
 
-     class TransactionResponse {
 
-         /**
 
-          *  The provider this is connected to, which will influence how its
 
-          *  methods will resolve its async inspection methods.
 
-          */
 
-         provider;
 
-         /**
 
-          *  The block number of the block that this transaction was included in.
 
-          *
 
-          *  This is ``null`` for pending transactions.
 
-          */
 
-         blockNumber;
 
-         /**
 
-          *  The blockHash of the block that this transaction was included in.
 
-          *
 
-          *  This is ``null`` for pending transactions.
 
-          */
 
-         blockHash;
 
-         /**
 
-          *  The index within the block that this transaction resides at.
 
-          */
 
-         index;
 
-         /**
 
-          *  The transaction hash.
 
-          */
 
-         hash;
 
-         /**
 
-          *  The [[link-eip-2718]] transaction envelope type. This is
 
-          *  ``0`` for legacy transactions types.
 
-          */
 
-         type;
 
-         /**
 
-          *  The receiver of this transaction.
 
-          *
 
-          *  If ``null``, then the transaction is an initcode transaction.
 
-          *  This means the result of executing the [[data]] will be deployed
 
-          *  as a new contract on chain (assuming it does not revert) and the
 
-          *  address may be computed using [[getCreateAddress]].
 
-          */
 
-         to;
 
-         /**
 
-          *  The sender of this transaction. It is implicitly computed
 
-          *  from the transaction pre-image hash (as the digest) and the
 
-          *  [[signature]] using ecrecover.
 
-          */
 
-         from;
 
-         /**
 
-          *  The nonce, which is used to prevent replay attacks and offer
 
-          *  a method to ensure transactions from a given sender are explicitly
 
-          *  ordered.
 
-          *
 
-          *  When sending a transaction, this must be equal to the number of
 
-          *  transactions ever sent by [[from]].
 
-          */
 
-         nonce;
 
-         /**
 
-          *  The maximum units of gas this transaction can consume. If execution
 
-          *  exceeds this, the entries transaction is reverted and the sender
 
-          *  is charged for the full amount, despite not state changes being made.
 
-          */
 
-         gasLimit;
 
-         /**
 
-          *  The gas price can have various values, depending on the network.
 
-          *
 
-          *  In modern networks, for transactions that are included this is
 
-          *  the //effective gas price// (the fee per gas that was actually
 
-          *  charged), while for transactions that have not been included yet
 
-          *  is the [[maxFeePerGas]].
 
-          *
 
-          *  For legacy transactions, or transactions on legacy networks, this
 
-          *  is the fee that will be charged per unit of gas the transaction
 
-          *  consumes.
 
-          */
 
-         gasPrice;
 
-         /**
 
-          *  The maximum priority fee (per unit of gas) to allow a
 
-          *  validator to charge the sender. This is inclusive of the
 
-          *  [[maxFeeFeePerGas]].
 
-          */
 
-         maxPriorityFeePerGas;
 
-         /**
 
-          *  The maximum fee (per unit of gas) to allow this transaction
 
-          *  to charge the sender.
 
-          */
 
-         maxFeePerGas;
 
-         /**
 
-          *  The [[link-eip-4844]] max fee per BLOb gas.
 
-          */
 
-         maxFeePerBlobGas;
 
-         /**
 
-          *  The data.
 
-          */
 
-         data;
 
-         /**
 
-          *  The value, in wei. Use [[formatEther]] to format this value
 
-          *  as ether.
 
-          */
 
-         value;
 
-         /**
 
-          *  The chain ID.
 
-          */
 
-         chainId;
 
-         /**
 
-          *  The signature.
 
-          */
 
-         signature;
 
-         /**
 
-          *  The [[link-eip-2930]] access list for transaction types that
 
-          *  support it, otherwise ``null``.
 
-          */
 
-         accessList;
 
-         /**
 
-          *  The [[link-eip-4844]] BLOb versioned hashes.
 
-          */
 
-         blobVersionedHashes;
 
-         #startBlock;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(tx, provider) {
 
-             this.provider = provider;
 
-             this.blockNumber = (tx.blockNumber != null) ? tx.blockNumber : null;
 
-             this.blockHash = (tx.blockHash != null) ? tx.blockHash : null;
 
-             this.hash = tx.hash;
 
-             this.index = tx.index;
 
-             this.type = tx.type;
 
-             this.from = tx.from;
 
-             this.to = tx.to || null;
 
-             this.gasLimit = tx.gasLimit;
 
-             this.nonce = tx.nonce;
 
-             this.data = tx.data;
 
-             this.value = tx.value;
 
-             this.gasPrice = tx.gasPrice;
 
-             this.maxPriorityFeePerGas = (tx.maxPriorityFeePerGas != null) ? tx.maxPriorityFeePerGas : null;
 
-             this.maxFeePerGas = (tx.maxFeePerGas != null) ? tx.maxFeePerGas : null;
 
-             this.maxFeePerBlobGas = (tx.maxFeePerBlobGas != null) ? tx.maxFeePerBlobGas : null;
 
-             this.chainId = tx.chainId;
 
-             this.signature = tx.signature;
 
-             this.accessList = (tx.accessList != null) ? tx.accessList : null;
 
-             this.blobVersionedHashes = (tx.blobVersionedHashes != null) ? tx.blobVersionedHashes : null;
 
-             this.#startBlock = -1;
 
-         }
 
-         /**
 
-          *  Returns a JSON-compatible representation of this transaction.
 
-          */
 
-         toJSON() {
 
-             const { blockNumber, blockHash, index, hash, type, to, from, nonce, data, signature, accessList, blobVersionedHashes } = this;
 
-             return {
 
-                 _type: "TransactionResponse",
 
-                 accessList, blockNumber, blockHash,
 
-                 blobVersionedHashes,
 
-                 chainId: toJson(this.chainId),
 
-                 data, from,
 
-                 gasLimit: toJson(this.gasLimit),
 
-                 gasPrice: toJson(this.gasPrice),
 
-                 hash,
 
-                 maxFeePerGas: toJson(this.maxFeePerGas),
 
-                 maxPriorityFeePerGas: toJson(this.maxPriorityFeePerGas),
 
-                 maxFeePerBlobGas: toJson(this.maxFeePerBlobGas),
 
-                 nonce, signature, to, index, type,
 
-                 value: toJson(this.value),
 
-             };
 
-         }
 
-         /**
 
-          *  Resolves to the Block that this transaction was included in.
 
-          *
 
-          *  This will return null if the transaction has not been included yet.
 
-          */
 
-         async getBlock() {
 
-             let blockNumber = this.blockNumber;
 
-             if (blockNumber == null) {
 
-                 const tx = await this.getTransaction();
 
-                 if (tx) {
 
-                     blockNumber = tx.blockNumber;
 
-                 }
 
-             }
 
-             if (blockNumber == null) {
 
-                 return null;
 
-             }
 
-             const block = this.provider.getBlock(blockNumber);
 
-             if (block == null) {
 
-                 throw new Error("TODO");
 
-             }
 
-             return block;
 
-         }
 
-         /**
 
-          *  Resolves to this transaction being re-requested from the
 
-          *  provider. This can be used if you have an unmined transaction
 
-          *  and wish to get an up-to-date populated instance.
 
-          */
 
-         async getTransaction() {
 
-             return this.provider.getTransaction(this.hash);
 
-         }
 
-         /**
 
-          *  Resolve to the number of confirmations this transaction has.
 
-          */
 
-         async confirmations() {
 
-             if (this.blockNumber == null) {
 
-                 const { tx, blockNumber } = await resolveProperties({
 
-                     tx: this.getTransaction(),
 
-                     blockNumber: this.provider.getBlockNumber()
 
-                 });
 
-                 // Not mined yet...
 
-                 if (tx == null || tx.blockNumber == null) {
 
-                     return 0;
 
-                 }
 
-                 return blockNumber - tx.blockNumber + 1;
 
-             }
 
-             const blockNumber = await this.provider.getBlockNumber();
 
-             return blockNumber - this.blockNumber + 1;
 
-         }
 
-         /**
 
-          *  Resolves once this transaction has been mined and has
 
-          *  %%confirms%% blocks including it (default: ``1``) with an
 
-          *  optional %%timeout%%.
 
-          *
 
-          *  This can resolve to ``null`` only if %%confirms%% is ``0``
 
-          *  and the transaction has not been mined, otherwise this will
 
-          *  wait until enough confirmations have completed.
 
-          */
 
-         async wait(_confirms, _timeout) {
 
-             const confirms = (_confirms == null) ? 1 : _confirms;
 
-             const timeout = (_timeout == null) ? 0 : _timeout;
 
-             let startBlock = this.#startBlock;
 
-             let nextScan = -1;
 
-             let stopScanning = (startBlock === -1) ? true : false;
 
-             const checkReplacement = async () => {
 
-                 // Get the current transaction count for this sender
 
-                 if (stopScanning) {
 
-                     return null;
 
-                 }
 
-                 const { blockNumber, nonce } = await resolveProperties({
 
-                     blockNumber: this.provider.getBlockNumber(),
 
-                     nonce: this.provider.getTransactionCount(this.from)
 
-                 });
 
-                 // No transaction or our nonce has not been mined yet; but we
 
-                 // can start scanning later when we do start
 
-                 if (nonce < this.nonce) {
 
-                     startBlock = blockNumber;
 
-                     return;
 
-                 }
 
-                 // We were mined; no replacement
 
-                 if (stopScanning) {
 
-                     return null;
 
-                 }
 
-                 const mined = await this.getTransaction();
 
-                 if (mined && mined.blockNumber != null) {
 
-                     return;
 
-                 }
 
-                 // We were replaced; start scanning for that transaction
 
-                 // Starting to scan; look back a few extra blocks for safety
 
-                 if (nextScan === -1) {
 
-                     nextScan = startBlock - 3;
 
-                     if (nextScan < this.#startBlock) {
 
-                         nextScan = this.#startBlock;
 
-                     }
 
-                 }
 
-                 while (nextScan <= blockNumber) {
 
-                     // Get the next block to scan
 
-                     if (stopScanning) {
 
-                         return null;
 
-                     }
 
-                     const block = await this.provider.getBlock(nextScan, true);
 
-                     // This should not happen; but we'll try again shortly
 
-                     if (block == null) {
 
-                         return;
 
-                     }
 
-                     // We were mined; no replacement
 
-                     for (const hash of block) {
 
-                         if (hash === this.hash) {
 
-                             return;
 
-                         }
 
-                     }
 
-                     // Search for the transaction that replaced us
 
-                     for (let i = 0; i < block.length; i++) {
 
-                         const tx = await block.getTransaction(i);
 
-                         if (tx.from === this.from && tx.nonce === this.nonce) {
 
-                             // Get the receipt
 
-                             if (stopScanning) {
 
-                                 return null;
 
-                             }
 
-                             const receipt = await this.provider.getTransactionReceipt(tx.hash);
 
-                             // This should not happen; but we'll try again shortly
 
-                             if (receipt == null) {
 
-                                 return;
 
-                             }
 
-                             // We will retry this on the next block (this case could be optimized)
 
-                             if ((blockNumber - receipt.blockNumber + 1) < confirms) {
 
-                                 return;
 
-                             }
 
-                             // The reason we were replaced
 
-                             let reason = "replaced";
 
-                             if (tx.data === this.data && tx.to === this.to && tx.value === this.value) {
 
-                                 reason = "repriced";
 
-                             }
 
-                             else if (tx.data === "0x" && tx.from === tx.to && tx.value === BN_0$2) {
 
-                                 reason = "cancelled";
 
-                             }
 
-                             assert(false, "transaction was replaced", "TRANSACTION_REPLACED", {
 
-                                 cancelled: (reason === "replaced" || reason === "cancelled"),
 
-                                 reason,
 
-                                 replacement: tx.replaceableTransaction(startBlock),
 
-                                 hash: tx.hash,
 
-                                 receipt
 
-                             });
 
-                         }
 
-                     }
 
-                     nextScan++;
 
-                 }
 
-                 return;
 
-             };
 
-             const checkReceipt = (receipt) => {
 
-                 if (receipt == null || receipt.status !== 0) {
 
-                     return receipt;
 
-                 }
 
-                 assert(false, "transaction execution reverted", "CALL_EXCEPTION", {
 
-                     action: "sendTransaction",
 
-                     data: null, reason: null, invocation: null, revert: null,
 
-                     transaction: {
 
-                         to: receipt.to,
 
-                         from: receipt.from,
 
-                         data: "" // @TODO: in v7, split out sendTransaction properties
 
-                     }, receipt
 
-                 });
 
-             };
 
-             const receipt = await this.provider.getTransactionReceipt(this.hash);
 
-             if (confirms === 0) {
 
-                 return checkReceipt(receipt);
 
-             }
 
-             if (receipt) {
 
-                 if ((await receipt.confirmations()) >= confirms) {
 
-                     return checkReceipt(receipt);
 
-                 }
 
-             }
 
-             else {
 
-                 // Check for a replacement; throws if a replacement was found
 
-                 await checkReplacement();
 
-                 // Allow null only when the confirms is 0
 
-                 if (confirms === 0) {
 
-                     return null;
 
-                 }
 
-             }
 
-             const waiter = new Promise((resolve, reject) => {
 
-                 // List of things to cancel when we have a result (one way or the other)
 
-                 const cancellers = [];
 
-                 const cancel = () => { cancellers.forEach((c) => c()); };
 
-                 // On cancel, stop scanning for replacements
 
-                 cancellers.push(() => { stopScanning = true; });
 
-                 // Set up any timeout requested
 
-                 if (timeout > 0) {
 
-                     const timer = setTimeout(() => {
 
-                         cancel();
 
-                         reject(makeError("wait for transaction timeout", "TIMEOUT"));
 
-                     }, timeout);
 
-                     cancellers.push(() => { clearTimeout(timer); });
 
-                 }
 
-                 const txListener = async (receipt) => {
 
-                     // Done; return it!
 
-                     if ((await receipt.confirmations()) >= confirms) {
 
-                         cancel();
 
-                         try {
 
-                             resolve(checkReceipt(receipt));
 
-                         }
 
-                         catch (error) {
 
-                             reject(error);
 
-                         }
 
-                     }
 
-                 };
 
-                 cancellers.push(() => { this.provider.off(this.hash, txListener); });
 
-                 this.provider.on(this.hash, txListener);
 
-                 // We support replacement detection; start checking
 
-                 if (startBlock >= 0) {
 
-                     const replaceListener = async () => {
 
-                         try {
 
-                             // Check for a replacement; this throws only if one is found
 
-                             await checkReplacement();
 
-                         }
 
-                         catch (error) {
 
-                             // We were replaced (with enough confirms); re-throw the error
 
-                             if (isError(error, "TRANSACTION_REPLACED")) {
 
-                                 cancel();
 
-                                 reject(error);
 
-                                 return;
 
-                             }
 
-                         }
 
-                         // Rescheudle a check on the next block
 
-                         if (!stopScanning) {
 
-                             this.provider.once("block", replaceListener);
 
-                         }
 
-                     };
 
-                     cancellers.push(() => { this.provider.off("block", replaceListener); });
 
-                     this.provider.once("block", replaceListener);
 
-                 }
 
-             });
 
-             return await waiter;
 
-         }
 
-         /**
 
-          *  Returns ``true`` if this transaction has been included.
 
-          *
 
-          *  This is effective only as of the time the TransactionResponse
 
-          *  was instantiated. To get up-to-date information, use
 
-          *  [[getTransaction]].
 
-          *
 
-          *  This provides a Type Guard that this transaction will have
 
-          *  non-null property values for properties that are null for
 
-          *  unmined transactions.
 
-          */
 
-         isMined() {
 
-             return (this.blockHash != null);
 
-         }
 
-         /**
 
-          *  Returns true if the transaction is a legacy (i.e. ``type == 0``)
 
-          *  transaction.
 
-          *
 
-          *  This provides a Type Guard that this transaction will have
 
-          *  the ``null``-ness for hardfork-specific properties set correctly.
 
-          */
 
-         isLegacy() {
 
-             return (this.type === 0);
 
-         }
 
-         /**
 
-          *  Returns true if the transaction is a Berlin (i.e. ``type == 1``)
 
-          *  transaction. See [[link-eip-2070]].
 
-          *
 
-          *  This provides a Type Guard that this transaction will have
 
-          *  the ``null``-ness for hardfork-specific properties set correctly.
 
-          */
 
-         isBerlin() {
 
-             return (this.type === 1);
 
-         }
 
-         /**
 
-          *  Returns true if the transaction is a London (i.e. ``type == 2``)
 
-          *  transaction. See [[link-eip-1559]].
 
-          *
 
-          *  This provides a Type Guard that this transaction will have
 
-          *  the ``null``-ness for hardfork-specific properties set correctly.
 
-          */
 
-         isLondon() {
 
-             return (this.type === 2);
 
-         }
 
-         /**
 
-          *  Returns true if hte transaction is a Cancun (i.e. ``type == 3``)
 
-          *  transaction. See [[link-eip-4844]].
 
-          */
 
-         isCancun() {
 
-             return (this.type === 3);
 
-         }
 
-         /**
 
-          *  Returns a filter which can be used to listen for orphan events
 
-          *  that evict this transaction.
 
-          */
 
-         removedEvent() {
 
-             assert(this.isMined(), "unmined transaction canot be orphaned", "UNSUPPORTED_OPERATION", { operation: "removeEvent()" });
 
-             return createRemovedTransactionFilter(this);
 
-         }
 
-         /**
 
-          *  Returns a filter which can be used to listen for orphan events
 
-          *  that re-order this event against %%other%%.
 
-          */
 
-         reorderedEvent(other) {
 
-             assert(this.isMined(), "unmined transaction canot be orphaned", "UNSUPPORTED_OPERATION", { operation: "removeEvent()" });
 
-             assert(!other || other.isMined(), "unmined 'other' transaction canot be orphaned", "UNSUPPORTED_OPERATION", { operation: "removeEvent()" });
 
-             return createReorderedTransactionFilter(this, other);
 
-         }
 
-         /**
 
-          *  Returns a new TransactionResponse instance which has the ability to
 
-          *  detect (and throw an error) if the transaction is replaced, which
 
-          *  will begin scanning at %%startBlock%%.
 
-          *
 
-          *  This should generally not be used by developers and is intended
 
-          *  primarily for internal use. Setting an incorrect %%startBlock%% can
 
-          *  have devastating performance consequences if used incorrectly.
 
-          */
 
-         replaceableTransaction(startBlock) {
 
-             assertArgument(Number.isInteger(startBlock) && startBlock >= 0, "invalid startBlock", "startBlock", startBlock);
 
-             const tx = new TransactionResponse(this, this.provider);
 
-             tx.#startBlock = startBlock;
 
-             return tx;
 
-         }
 
-     }
 
-     function createOrphanedBlockFilter(block) {
 
-         return { orphan: "drop-block", hash: block.hash, number: block.number };
 
-     }
 
-     function createReorderedTransactionFilter(tx, other) {
 
-         return { orphan: "reorder-transaction", tx, other };
 
-     }
 
-     function createRemovedTransactionFilter(tx) {
 
-         return { orphan: "drop-transaction", tx };
 
-     }
 
-     function createRemovedLogFilter(log) {
 
-         return { orphan: "drop-log", log: {
 
-                 transactionHash: log.transactionHash,
 
-                 blockHash: log.blockHash,
 
-                 blockNumber: log.blockNumber,
 
-                 address: log.address,
 
-                 data: log.data,
 
-                 topics: Object.freeze(log.topics.slice()),
 
-                 index: log.index
 
-             } };
 
-     }
 
-     // import from provider.ts instead of index.ts to prevent circular dep
 
-     // from EtherscanProvider
 
-     /**
 
-      *  An **EventLog** contains additional properties parsed from the [[Log]].
 
-      */
 
-     class EventLog extends Log {
 
-         /**
 
-          *  The Contract Interface.
 
-          */
 
-         interface;
 
-         /**
 
-          *  The matching event.
 
-          */
 
-         fragment;
 
-         /**
 
-          *  The parsed arguments passed to the event by ``emit``.
 
-          */
 
-         args;
 
-         /**
 
-          * @_ignore:
 
-          */
 
-         constructor(log, iface, fragment) {
 
-             super(log, log.provider);
 
-             const args = iface.decodeEventLog(fragment, log.data, log.topics);
 
-             defineProperties(this, { args, fragment, interface: iface });
 
-         }
 
-         /**
 
-          *  The name of the event.
 
-          */
 
-         get eventName() { return this.fragment.name; }
 
-         /**
 
-          *  The signature of the event.
 
-          */
 
-         get eventSignature() { return this.fragment.format(); }
 
-     }
 
-     /**
 
-      *  An **EventLog** contains additional properties parsed from the [[Log]].
 
-      */
 
-     class UndecodedEventLog extends Log {
 
-         /**
 
-          *  The error encounted when trying to decode the log.
 
-          */
 
-         error;
 
-         /**
 
-          * @_ignore:
 
-          */
 
-         constructor(log, error) {
 
-             super(log, log.provider);
 
-             defineProperties(this, { error });
 
-         }
 
-     }
 
-     /**
 
-      *  A **ContractTransactionReceipt** includes the parsed logs from a
 
-      *  [[TransactionReceipt]].
 
-      */
 
-     class ContractTransactionReceipt extends TransactionReceipt {
 
-         #iface;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(iface, provider, tx) {
 
-             super(tx, provider);
 
-             this.#iface = iface;
 
-         }
 
-         /**
 
-          *  The parsed logs for any [[Log]] which has a matching event in the
 
-          *  Contract ABI.
 
-          */
 
-         get logs() {
 
-             return super.logs.map((log) => {
 
-                 const fragment = log.topics.length ? this.#iface.getEvent(log.topics[0]) : null;
 
-                 if (fragment) {
 
-                     try {
 
-                         return new EventLog(log, this.#iface, fragment);
 
-                     }
 
-                     catch (error) {
 
-                         return new UndecodedEventLog(log, error);
 
-                     }
 
-                 }
 
-                 return log;
 
-             });
 
-         }
 
-     }
 
-     /**
 
-      *  A **ContractTransactionResponse** will return a
 
-      *  [[ContractTransactionReceipt]] when waited on.
 
-      */
 
-     class ContractTransactionResponse extends TransactionResponse {
 
-         #iface;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(iface, provider, tx) {
 
-             super(tx, provider);
 
-             this.#iface = iface;
 
-         }
 
-         /**
 
-          *  Resolves once this transaction has been mined and has
 
-          *  %%confirms%% blocks including it (default: ``1``) with an
 
-          *  optional %%timeout%%.
 
-          *
 
-          *  This can resolve to ``null`` only if %%confirms%% is ``0``
 
-          *  and the transaction has not been mined, otherwise this will
 
-          *  wait until enough confirmations have completed.
 
-          */
 
-         async wait(confirms, timeout) {
 
-             const receipt = await super.wait(confirms, timeout);
 
-             if (receipt == null) {
 
-                 return null;
 
-             }
 
-             return new ContractTransactionReceipt(this.#iface, this.provider, receipt);
 
-         }
 
-     }
 
-     /**
 
-      *  A **ContractUnknownEventPayload** is included as the last parameter to
 
-      *  Contract Events when the event does not match any events in the ABI.
 
-      */
 
-     class ContractUnknownEventPayload extends EventPayload {
 
-         /**
 
-          *  The log with no matching events.
 
-          */
 
-         log;
 
-         /**
 
-          *  @_event:
 
-          */
 
-         constructor(contract, listener, filter, log) {
 
-             super(contract, listener, filter);
 
-             defineProperties(this, { log });
 
-         }
 
-         /**
 
-          *  Resolves to the block the event occured in.
 
-          */
 
-         async getBlock() {
 
-             return await this.log.getBlock();
 
-         }
 
-         /**
 
-          *  Resolves to the transaction the event occured in.
 
-          */
 
-         async getTransaction() {
 
-             return await this.log.getTransaction();
 
-         }
 
-         /**
 
-          *  Resolves to the transaction receipt the event occured in.
 
-          */
 
-         async getTransactionReceipt() {
 
-             return await this.log.getTransactionReceipt();
 
-         }
 
-     }
 
-     /**
 
-      *  A **ContractEventPayload** is included as the last parameter to
 
-      *  Contract Events when the event is known.
 
-      */
 
-     class ContractEventPayload extends ContractUnknownEventPayload {
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(contract, listener, filter, fragment, _log) {
 
-             super(contract, listener, filter, new EventLog(_log, contract.interface, fragment));
 
-             const args = contract.interface.decodeEventLog(fragment, this.log.data, this.log.topics);
 
-             defineProperties(this, { args, fragment });
 
-         }
 
-         /**
 
-          *  The event name.
 
-          */
 
-         get eventName() {
 
-             return this.fragment.name;
 
-         }
 
-         /**
 
-          *  The event signature.
 
-          */
 
-         get eventSignature() {
 
-             return this.fragment.format();
 
-         }
 
-     }
 
-     const BN_0$1 = BigInt(0);
 
-     function canCall(value) {
 
-         return (value && typeof (value.call) === "function");
 
-     }
 
-     function canEstimate(value) {
 
-         return (value && typeof (value.estimateGas) === "function");
 
-     }
 
-     function canResolve(value) {
 
-         return (value && typeof (value.resolveName) === "function");
 
-     }
 
-     function canSend(value) {
 
-         return (value && typeof (value.sendTransaction) === "function");
 
-     }
 
-     function getResolver(value) {
 
-         if (value != null) {
 
-             if (canResolve(value)) {
 
-                 return value;
 
-             }
 
-             if (value.provider) {
 
-                 return value.provider;
 
-             }
 
-         }
 
-         return undefined;
 
-     }
 
-     class PreparedTopicFilter {
 
-         #filter;
 
-         fragment;
 
-         constructor(contract, fragment, args) {
 
-             defineProperties(this, { fragment });
 
-             if (fragment.inputs.length < args.length) {
 
-                 throw new Error("too many arguments");
 
-             }
 
-             // Recursively descend into args and resolve any addresses
 
-             const runner = getRunner(contract.runner, "resolveName");
 
-             const resolver = canResolve(runner) ? runner : null;
 
-             this.#filter = (async function () {
 
-                 const resolvedArgs = await Promise.all(fragment.inputs.map((param, index) => {
 
-                     const arg = args[index];
 
-                     if (arg == null) {
 
-                         return null;
 
-                     }
 
-                     return param.walkAsync(args[index], (type, value) => {
 
-                         if (type === "address") {
 
-                             if (Array.isArray(value)) {
 
-                                 return Promise.all(value.map((v) => resolveAddress(v, resolver)));
 
-                             }
 
-                             return resolveAddress(value, resolver);
 
-                         }
 
-                         return value;
 
-                     });
 
-                 }));
 
-                 return contract.interface.encodeFilterTopics(fragment, resolvedArgs);
 
-             })();
 
-         }
 
-         getTopicFilter() {
 
-             return this.#filter;
 
-         }
 
-     }
 
-     // A = Arguments passed in as a tuple
 
-     // R = The result type of the call (i.e. if only one return type,
 
-     //     the qualified type, otherwise Result)
 
-     // D = The type the default call will return (i.e. R for view/pure,
 
-     //     TransactionResponse otherwise)
 
-     //export interface ContractMethod<A extends Array<any> = Array<any>, R = any, D extends R | ContractTransactionResponse = ContractTransactionResponse> {
 
-     function getRunner(value, feature) {
 
-         if (value == null) {
 
-             return null;
 
-         }
 
-         if (typeof (value[feature]) === "function") {
 
-             return value;
 
-         }
 
-         if (value.provider && typeof (value.provider[feature]) === "function") {
 
-             return value.provider;
 
-         }
 
-         return null;
 
-     }
 
-     function getProvider(value) {
 
-         if (value == null) {
 
-             return null;
 
-         }
 
-         return value.provider || null;
 
-     }
 
-     /**
 
-      *  @_ignore:
 
-      */
 
-     async function copyOverrides(arg, allowed) {
 
-         // Make sure the overrides passed in are a valid overrides object
 
-         const _overrides = Typed.dereference(arg, "overrides");
 
-         assertArgument(typeof (_overrides) === "object", "invalid overrides parameter", "overrides", arg);
 
-         // Create a shallow copy (we'll deep-ify anything needed during normalizing)
 
-         const overrides = copyRequest(_overrides);
 
-         assertArgument(overrides.to == null || (allowed || []).indexOf("to") >= 0, "cannot override to", "overrides.to", overrides.to);
 
-         assertArgument(overrides.data == null || (allowed || []).indexOf("data") >= 0, "cannot override data", "overrides.data", overrides.data);
 
-         // Resolve any from
 
-         if (overrides.from) {
 
-             overrides.from = overrides.from;
 
-         }
 
-         return overrides;
 
-     }
 
-     /**
 
-      *  @_ignore:
 
-      */
 
-     async function resolveArgs(_runner, inputs, args) {
 
-         // Recursively descend into args and resolve any addresses
 
-         const runner = getRunner(_runner, "resolveName");
 
-         const resolver = canResolve(runner) ? runner : null;
 
-         return await Promise.all(inputs.map((param, index) => {
 
-             return param.walkAsync(args[index], (type, value) => {
 
-                 value = Typed.dereference(value, type);
 
-                 if (type === "address") {
 
-                     return resolveAddress(value, resolver);
 
-                 }
 
-                 return value;
 
-             });
 
-         }));
 
-     }
 
-     function buildWrappedFallback(contract) {
 
-         const populateTransaction = async function (overrides) {
 
-             // If an overrides was passed in, copy it and normalize the values
 
-             const tx = (await copyOverrides(overrides, ["data"]));
 
-             tx.to = await contract.getAddress();
 
-             if (tx.from) {
 
-                 tx.from = await resolveAddress(tx.from, getResolver(contract.runner));
 
-             }
 
-             const iface = contract.interface;
 
-             const noValue = (getBigInt((tx.value || BN_0$1), "overrides.value") === BN_0$1);
 
-             const noData = ((tx.data || "0x") === "0x");
 
-             if (iface.fallback && !iface.fallback.payable && iface.receive && !noData && !noValue) {
 
-                 assertArgument(false, "cannot send data to receive or send value to non-payable fallback", "overrides", overrides);
 
-             }
 
-             assertArgument(iface.fallback || noData, "cannot send data to receive-only contract", "overrides.data", tx.data);
 
-             // Only allow payable contracts to set non-zero value
 
-             const payable = iface.receive || (iface.fallback && iface.fallback.payable);
 
-             assertArgument(payable || noValue, "cannot send value to non-payable fallback", "overrides.value", tx.value);
 
-             // Only allow fallback contracts to set non-empty data
 
-             assertArgument(iface.fallback || noData, "cannot send data to receive-only contract", "overrides.data", tx.data);
 
-             return tx;
 
-         };
 
-         const staticCall = async function (overrides) {
 
-             const runner = getRunner(contract.runner, "call");
 
-             assert(canCall(runner), "contract runner does not support calling", "UNSUPPORTED_OPERATION", { operation: "call" });
 
-             const tx = await populateTransaction(overrides);
 
-             try {
 
-                 return await runner.call(tx);
 
-             }
 
-             catch (error) {
 
-                 if (isCallException(error) && error.data) {
 
-                     throw contract.interface.makeError(error.data, tx);
 
-                 }
 
-                 throw error;
 
-             }
 
-         };
 
-         const send = async function (overrides) {
 
-             const runner = contract.runner;
 
-             assert(canSend(runner), "contract runner does not support sending transactions", "UNSUPPORTED_OPERATION", { operation: "sendTransaction" });
 
-             const tx = await runner.sendTransaction(await populateTransaction(overrides));
 
-             const provider = getProvider(contract.runner);
 
-             // @TODO: the provider can be null; make a custom dummy provider that will throw a
 
-             // meaningful error
 
-             return new ContractTransactionResponse(contract.interface, provider, tx);
 
-         };
 
-         const estimateGas = async function (overrides) {
 
-             const runner = getRunner(contract.runner, "estimateGas");
 
-             assert(canEstimate(runner), "contract runner does not support gas estimation", "UNSUPPORTED_OPERATION", { operation: "estimateGas" });
 
-             return await runner.estimateGas(await populateTransaction(overrides));
 
-         };
 
-         const method = async (overrides) => {
 
-             return await send(overrides);
 
-         };
 
-         defineProperties(method, {
 
-             _contract: contract,
 
-             estimateGas,
 
-             populateTransaction,
 
-             send, staticCall
 
-         });
 
-         return method;
 
-     }
 
-     function buildWrappedMethod(contract, key) {
 
-         const getFragment = function (...args) {
 
-             const fragment = contract.interface.getFunction(key, args);
 
-             assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
 
-                 operation: "fragment",
 
-                 info: { key, args }
 
-             });
 
-             return fragment;
 
-         };
 
-         const populateTransaction = async function (...args) {
 
-             const fragment = getFragment(...args);
 
-             // If an overrides was passed in, copy it and normalize the values
 
-             let overrides = {};
 
-             if (fragment.inputs.length + 1 === args.length) {
 
-                 overrides = await copyOverrides(args.pop());
 
-                 if (overrides.from) {
 
-                     overrides.from = await resolveAddress(overrides.from, getResolver(contract.runner));
 
-                 }
 
-             }
 
-             if (fragment.inputs.length !== args.length) {
 
-                 throw new Error("internal error: fragment inputs doesn't match arguments; should not happen");
 
-             }
 
-             const resolvedArgs = await resolveArgs(contract.runner, fragment.inputs, args);
 
-             return Object.assign({}, overrides, await resolveProperties({
 
-                 to: contract.getAddress(),
 
-                 data: contract.interface.encodeFunctionData(fragment, resolvedArgs)
 
-             }));
 
-         };
 
-         const staticCall = async function (...args) {
 
-             const result = await staticCallResult(...args);
 
-             if (result.length === 1) {
 
-                 return result[0];
 
-             }
 
-             return result;
 
-         };
 
-         const send = async function (...args) {
 
-             const runner = contract.runner;
 
-             assert(canSend(runner), "contract runner does not support sending transactions", "UNSUPPORTED_OPERATION", { operation: "sendTransaction" });
 
-             const tx = await runner.sendTransaction(await populateTransaction(...args));
 
-             const provider = getProvider(contract.runner);
 
-             // @TODO: the provider can be null; make a custom dummy provider that will throw a
 
-             // meaningful error
 
-             return new ContractTransactionResponse(contract.interface, provider, tx);
 
-         };
 
-         const estimateGas = async function (...args) {
 
-             const runner = getRunner(contract.runner, "estimateGas");
 
-             assert(canEstimate(runner), "contract runner does not support gas estimation", "UNSUPPORTED_OPERATION", { operation: "estimateGas" });
 
-             return await runner.estimateGas(await populateTransaction(...args));
 
-         };
 
-         const staticCallResult = async function (...args) {
 
-             const runner = getRunner(contract.runner, "call");
 
-             assert(canCall(runner), "contract runner does not support calling", "UNSUPPORTED_OPERATION", { operation: "call" });
 
-             const tx = await populateTransaction(...args);
 
-             let result = "0x";
 
-             try {
 
-                 result = await runner.call(tx);
 
-             }
 
-             catch (error) {
 
-                 if (isCallException(error) && error.data) {
 
-                     throw contract.interface.makeError(error.data, tx);
 
-                 }
 
-                 throw error;
 
-             }
 
-             const fragment = getFragment(...args);
 
-             return contract.interface.decodeFunctionResult(fragment, result);
 
-         };
 
-         const method = async (...args) => {
 
-             const fragment = getFragment(...args);
 
-             if (fragment.constant) {
 
-                 return await staticCall(...args);
 
-             }
 
-             return await send(...args);
 
-         };
 
-         defineProperties(method, {
 
-             name: contract.interface.getFunctionName(key),
 
-             _contract: contract, _key: key,
 
-             getFragment,
 
-             estimateGas,
 
-             populateTransaction,
 
-             send, staticCall, staticCallResult,
 
-         });
 
-         // Only works on non-ambiguous keys (refined fragment is always non-ambiguous)
 
-         Object.defineProperty(method, "fragment", {
 
-             configurable: false,
 
-             enumerable: true,
 
-             get: () => {
 
-                 const fragment = contract.interface.getFunction(key);
 
-                 assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
 
-                     operation: "fragment",
 
-                     info: { key }
 
-                 });
 
-                 return fragment;
 
-             }
 
-         });
 
-         return method;
 
-     }
 
-     function buildWrappedEvent(contract, key) {
 
-         const getFragment = function (...args) {
 
-             const fragment = contract.interface.getEvent(key, args);
 
-             assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
 
-                 operation: "fragment",
 
-                 info: { key, args }
 
-             });
 
-             return fragment;
 
-         };
 
-         const method = function (...args) {
 
-             return new PreparedTopicFilter(contract, getFragment(...args), args);
 
-         };
 
-         defineProperties(method, {
 
-             name: contract.interface.getEventName(key),
 
-             _contract: contract, _key: key,
 
-             getFragment
 
-         });
 
-         // Only works on non-ambiguous keys (refined fragment is always non-ambiguous)
 
-         Object.defineProperty(method, "fragment", {
 
-             configurable: false,
 
-             enumerable: true,
 
-             get: () => {
 
-                 const fragment = contract.interface.getEvent(key);
 
-                 assert(fragment, "no matching fragment", "UNSUPPORTED_OPERATION", {
 
-                     operation: "fragment",
 
-                     info: { key }
 
-                 });
 
-                 return fragment;
 
-             }
 
-         });
 
-         return method;
 
-     }
 
-     // The combination of TypeScrype, Private Fields and Proxies makes
 
-     // the world go boom; so we hide variables with some trickery keeping
 
-     // a symbol attached to each BaseContract which its sub-class (even
 
-     // via a Proxy) can reach and use to look up its internal values.
 
-     const internal = Symbol.for("_ethersInternal_contract");
 
-     const internalValues = new WeakMap();
 
-     function setInternal(contract, values) {
 
-         internalValues.set(contract[internal], values);
 
-     }
 
-     function getInternal(contract) {
 
-         return internalValues.get(contract[internal]);
 
-     }
 
-     function isDeferred(value) {
 
-         return (value && typeof (value) === "object" && ("getTopicFilter" in value) &&
 
-             (typeof (value.getTopicFilter) === "function") && value.fragment);
 
-     }
 
-     async function getSubInfo(contract, event) {
 
-         let topics;
 
-         let fragment = null;
 
-         // Convert named events to topicHash and get the fragment for
 
-         // events which need deconstructing.
 
-         if (Array.isArray(event)) {
 
-             const topicHashify = function (name) {
 
-                 if (isHexString(name, 32)) {
 
-                     return name;
 
-                 }
 
-                 const fragment = contract.interface.getEvent(name);
 
-                 assertArgument(fragment, "unknown fragment", "name", name);
 
-                 return fragment.topicHash;
 
-             };
 
-             // Array of Topics and Names; e.g. `[ "0x1234...89ab", "Transfer(address)" ]`
 
-             topics = event.map((e) => {
 
-                 if (e == null) {
 
-                     return null;
 
-                 }
 
-                 if (Array.isArray(e)) {
 
-                     return e.map(topicHashify);
 
-                 }
 
-                 return topicHashify(e);
 
-             });
 
-         }
 
-         else if (event === "*") {
 
-             topics = [null];
 
-         }
 
-         else if (typeof (event) === "string") {
 
-             if (isHexString(event, 32)) {
 
-                 // Topic Hash
 
-                 topics = [event];
 
-             }
 
-             else {
 
-                 // Name or Signature; e.g. `"Transfer", `"Transfer(address)"`
 
-                 fragment = contract.interface.getEvent(event);
 
-                 assertArgument(fragment, "unknown fragment", "event", event);
 
-                 topics = [fragment.topicHash];
 
-             }
 
-         }
 
-         else if (isDeferred(event)) {
 
-             // Deferred Topic Filter; e.g. `contract.filter.Transfer(from)`
 
-             topics = await event.getTopicFilter();
 
-         }
 
-         else if ("fragment" in event) {
 
-             // ContractEvent; e.g. `contract.filter.Transfer`
 
-             fragment = event.fragment;
 
-             topics = [fragment.topicHash];
 
-         }
 
-         else {
 
-             assertArgument(false, "unknown event name", "event", event);
 
-         }
 
-         // Normalize topics and sort TopicSets
 
-         topics = topics.map((t) => {
 
-             if (t == null) {
 
-                 return null;
 
-             }
 
-             if (Array.isArray(t)) {
 
-                 const items = Array.from(new Set(t.map((t) => t.toLowerCase())).values());
 
-                 if (items.length === 1) {
 
-                     return items[0];
 
-                 }
 
-                 items.sort();
 
-                 return items;
 
-             }
 
-             return t.toLowerCase();
 
-         });
 
-         const tag = topics.map((t) => {
 
-             if (t == null) {
 
-                 return "null";
 
-             }
 
-             if (Array.isArray(t)) {
 
-                 return t.join("|");
 
-             }
 
-             return t;
 
-         }).join("&");
 
-         return { fragment, tag, topics };
 
-     }
 
-     async function hasSub(contract, event) {
 
-         const { subs } = getInternal(contract);
 
-         return subs.get((await getSubInfo(contract, event)).tag) || null;
 
-     }
 
-     async function getSub(contract, operation, event) {
 
-         // Make sure our runner can actually subscribe to events
 
-         const provider = getProvider(contract.runner);
 
-         assert(provider, "contract runner does not support subscribing", "UNSUPPORTED_OPERATION", { operation });
 
-         const { fragment, tag, topics } = await getSubInfo(contract, event);
 
-         const { addr, subs } = getInternal(contract);
 
-         let sub = subs.get(tag);
 
-         if (!sub) {
 
-             const address = (addr ? addr : contract);
 
-             const filter = { address, topics };
 
-             const listener = (log) => {
 
-                 let foundFragment = fragment;
 
-                 if (foundFragment == null) {
 
-                     try {
 
-                         foundFragment = contract.interface.getEvent(log.topics[0]);
 
-                     }
 
-                     catch (error) { }
 
-                 }
 
-                 // If fragment is null, we do not deconstruct the args to emit
 
-                 if (foundFragment) {
 
-                     const _foundFragment = foundFragment;
 
-                     const args = fragment ? contract.interface.decodeEventLog(fragment, log.data, log.topics) : [];
 
-                     emit(contract, event, args, (listener) => {
 
-                         return new ContractEventPayload(contract, listener, event, _foundFragment, log);
 
-                     });
 
-                 }
 
-                 else {
 
-                     emit(contract, event, [], (listener) => {
 
-                         return new ContractUnknownEventPayload(contract, listener, event, log);
 
-                     });
 
-                 }
 
-             };
 
-             let starting = [];
 
-             const start = () => {
 
-                 if (starting.length) {
 
-                     return;
 
-                 }
 
-                 starting.push(provider.on(filter, listener));
 
-             };
 
-             const stop = async () => {
 
-                 if (starting.length == 0) {
 
-                     return;
 
-                 }
 
-                 let started = starting;
 
-                 starting = [];
 
-                 await Promise.all(started);
 
-                 provider.off(filter, listener);
 
-             };
 
-             sub = { tag, listeners: [], start, stop };
 
-             subs.set(tag, sub);
 
-         }
 
-         return sub;
 
-     }
 
-     // We use this to ensure one emit resolves before firing the next to
 
-     // ensure correct ordering (note this cannot throw and just adds the
 
-     // notice to the event queu using setTimeout).
 
-     let lastEmit = Promise.resolve();
 
-     async function _emit(contract, event, args, payloadFunc) {
 
-         await lastEmit;
 
-         const sub = await hasSub(contract, event);
 
-         if (!sub) {
 
-             return false;
 
-         }
 
-         const count = sub.listeners.length;
 
-         sub.listeners = sub.listeners.filter(({ listener, once }) => {
 
-             const passArgs = Array.from(args);
 
-             if (payloadFunc) {
 
-                 passArgs.push(payloadFunc(once ? null : listener));
 
-             }
 
-             try {
 
-                 listener.call(contract, ...passArgs);
 
-             }
 
-             catch (error) { }
 
-             return !once;
 
-         });
 
-         if (sub.listeners.length === 0) {
 
-             sub.stop();
 
-             getInternal(contract).subs.delete(sub.tag);
 
-         }
 
-         return (count > 0);
 
-     }
 
-     async function emit(contract, event, args, payloadFunc) {
 
-         try {
 
-             await lastEmit;
 
-         }
 
-         catch (error) { }
 
-         const resultPromise = _emit(contract, event, args, payloadFunc);
 
-         lastEmit = resultPromise;
 
-         return await resultPromise;
 
-     }
 
-     const passProperties = ["then"];
 
-     class BaseContract {
 
-         /**
 
-          *  The target to connect to.
 
-          *
 
-          *  This can be an address, ENS name or any [[Addressable]], such as
 
-          *  another contract. To get the resovled address, use the ``getAddress``
 
-          *  method.
 
-          */
 
-         target;
 
-         /**
 
-          *  The contract Interface.
 
-          */
 
-         interface;
 
-         /**
 
-          *  The connected runner. This is generally a [[Provider]] or a
 
-          *  [[Signer]], which dictates what operations are supported.
 
-          *
 
-          *  For example, a **Contract** connected to a [[Provider]] may
 
-          *  only execute read-only operations.
 
-          */
 
-         runner;
 
-         /**
 
-          *  All the Events available on this contract.
 
-          */
 
-         filters;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         [internal];
 
-         /**
 
-          *  The fallback or receive function if any.
 
-          */
 
-         fallback;
 
-         /**
 
-          *  Creates a new contract connected to %%target%% with the %%abi%% and
 
-          *  optionally connected to a %%runner%% to perform operations on behalf
 
-          *  of.
 
-          */
 
-         constructor(target, abi, runner, _deployTx) {
 
-             assertArgument(typeof (target) === "string" || isAddressable(target), "invalid value for Contract target", "target", target);
 
-             if (runner == null) {
 
-                 runner = null;
 
-             }
 
-             const iface = Interface.from(abi);
 
-             defineProperties(this, { target, runner, interface: iface });
 
-             Object.defineProperty(this, internal, { value: {} });
 
-             let addrPromise;
 
-             let addr = null;
 
-             let deployTx = null;
 
-             if (_deployTx) {
 
-                 const provider = getProvider(runner);
 
-                 // @TODO: the provider can be null; make a custom dummy provider that will throw a
 
-                 // meaningful error
 
-                 deployTx = new ContractTransactionResponse(this.interface, provider, _deployTx);
 
-             }
 
-             let subs = new Map();
 
-             // Resolve the target as the address
 
-             if (typeof (target) === "string") {
 
-                 if (isHexString(target)) {
 
-                     addr = target;
 
-                     addrPromise = Promise.resolve(target);
 
-                 }
 
-                 else {
 
-                     const resolver = getRunner(runner, "resolveName");
 
-                     if (!canResolve(resolver)) {
 
-                         throw makeError("contract runner does not support name resolution", "UNSUPPORTED_OPERATION", {
 
-                             operation: "resolveName"
 
-                         });
 
-                     }
 
-                     addrPromise = resolver.resolveName(target).then((addr) => {
 
-                         if (addr == null) {
 
-                             throw makeError("an ENS name used for a contract target must be correctly configured", "UNCONFIGURED_NAME", {
 
-                                 value: target
 
-                             });
 
-                         }
 
-                         getInternal(this).addr = addr;
 
-                         return addr;
 
-                     });
 
-                 }
 
-             }
 
-             else {
 
-                 addrPromise = target.getAddress().then((addr) => {
 
-                     if (addr == null) {
 
-                         throw new Error("TODO");
 
-                     }
 
-                     getInternal(this).addr = addr;
 
-                     return addr;
 
-                 });
 
-             }
 
-             // Set our private values
 
-             setInternal(this, { addrPromise, addr, deployTx, subs });
 
-             // Add the event filters
 
-             const filters = new Proxy({}, {
 
-                 get: (target, prop, receiver) => {
 
-                     // Pass important checks (like `then` for Promise) through
 
-                     if (typeof (prop) === "symbol" || passProperties.indexOf(prop) >= 0) {
 
-                         return Reflect.get(target, prop, receiver);
 
-                     }
 
-                     try {
 
-                         return this.getEvent(prop);
 
-                     }
 
-                     catch (error) {
 
-                         if (!isError(error, "INVALID_ARGUMENT") || error.argument !== "key") {
 
-                             throw error;
 
-                         }
 
-                     }
 
-                     return undefined;
 
-                 },
 
-                 has: (target, prop) => {
 
-                     // Pass important checks (like `then` for Promise) through
 
-                     if (passProperties.indexOf(prop) >= 0) {
 
-                         return Reflect.has(target, prop);
 
-                     }
 
-                     return Reflect.has(target, prop) || this.interface.hasEvent(String(prop));
 
-                 }
 
-             });
 
-             defineProperties(this, { filters });
 
-             defineProperties(this, {
 
-                 fallback: ((iface.receive || iface.fallback) ? (buildWrappedFallback(this)) : null)
 
-             });
 
-             // Return a Proxy that will respond to functions
 
-             return new Proxy(this, {
 
-                 get: (target, prop, receiver) => {
 
-                     if (typeof (prop) === "symbol" || prop in target || passProperties.indexOf(prop) >= 0) {
 
-                         return Reflect.get(target, prop, receiver);
 
-                     }
 
-                     // Undefined properties should return undefined
 
-                     try {
 
-                         return target.getFunction(prop);
 
-                     }
 
-                     catch (error) {
 
-                         if (!isError(error, "INVALID_ARGUMENT") || error.argument !== "key") {
 
-                             throw error;
 
-                         }
 
-                     }
 
-                     return undefined;
 
-                 },
 
-                 has: (target, prop) => {
 
-                     if (typeof (prop) === "symbol" || prop in target || passProperties.indexOf(prop) >= 0) {
 
-                         return Reflect.has(target, prop);
 
-                     }
 
-                     return target.interface.hasFunction(prop);
 
-                 }
 
-             });
 
-         }
 
-         /**
 
-          *  Return a new Contract instance with the same target and ABI, but
 
-          *  a different %%runner%%.
 
-          */
 
-         connect(runner) {
 
-             return new BaseContract(this.target, this.interface, runner);
 
-         }
 
-         /**
 
-          *  Return a new Contract instance with the same ABI and runner, but
 
-          *  a different %%target%%.
 
-          */
 
-         attach(target) {
 
-             return new BaseContract(target, this.interface, this.runner);
 
-         }
 
-         /**
 
-          *  Return the resolved address of this Contract.
 
-          */
 
-         async getAddress() { return await getInternal(this).addrPromise; }
 
-         /**
 
-          *  Return the deployed bytecode or null if no bytecode is found.
 
-          */
 
-         async getDeployedCode() {
 
-             const provider = getProvider(this.runner);
 
-             assert(provider, "runner does not support .provider", "UNSUPPORTED_OPERATION", { operation: "getDeployedCode" });
 
-             const code = await provider.getCode(await this.getAddress());
 
-             if (code === "0x") {
 
-                 return null;
 
-             }
 
-             return code;
 
-         }
 
-         /**
 
-          *  Resolve to this Contract once the bytecode has been deployed, or
 
-          *  resolve immediately if already deployed.
 
-          */
 
-         async waitForDeployment() {
 
-             // We have the deployement transaction; just use that (throws if deployement fails)
 
-             const deployTx = this.deploymentTransaction();
 
-             if (deployTx) {
 
-                 await deployTx.wait();
 
-                 return this;
 
-             }
 
-             // Check for code
 
-             const code = await this.getDeployedCode();
 
-             if (code != null) {
 
-                 return this;
 
-             }
 
-             // Make sure we can subscribe to a provider event
 
-             const provider = getProvider(this.runner);
 
-             assert(provider != null, "contract runner does not support .provider", "UNSUPPORTED_OPERATION", { operation: "waitForDeployment" });
 
-             return new Promise((resolve, reject) => {
 
-                 const checkCode = async () => {
 
-                     try {
 
-                         const code = await this.getDeployedCode();
 
-                         if (code != null) {
 
-                             return resolve(this);
 
-                         }
 
-                         provider.once("block", checkCode);
 
-                     }
 
-                     catch (error) {
 
-                         reject(error);
 
-                     }
 
-                 };
 
-                 checkCode();
 
-             });
 
-         }
 
-         /**
 
-          *  Return the transaction used to deploy this contract.
 
-          *
 
-          *  This is only available if this instance was returned from a
 
-          *  [[ContractFactory]].
 
-          */
 
-         deploymentTransaction() {
 
-             return getInternal(this).deployTx;
 
-         }
 
-         /**
 
-          *  Return the function for a given name. This is useful when a contract
 
-          *  method name conflicts with a JavaScript name such as ``prototype`` or
 
-          *  when using a Contract programatically.
 
-          */
 
-         getFunction(key) {
 
-             if (typeof (key) !== "string") {
 
-                 key = key.format();
 
-             }
 
-             const func = buildWrappedMethod(this, key);
 
-             return func;
 
-         }
 
-         /**
 
-          *  Return the event for a given name. This is useful when a contract
 
-          *  event name conflicts with a JavaScript name such as ``prototype`` or
 
-          *  when using a Contract programatically.
 
-          */
 
-         getEvent(key) {
 
-             if (typeof (key) !== "string") {
 
-                 key = key.format();
 
-             }
 
-             return buildWrappedEvent(this, key);
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         async queryTransaction(hash) {
 
-             throw new Error("@TODO");
 
-         }
 
-         /*
 
-         // @TODO: this is a non-backwards compatible change, but will be added
 
-         //        in v7 and in a potential SmartContract class in an upcoming
 
-         //        v6 release
 
-         async getTransactionReceipt(hash: string): Promise<null | ContractTransactionReceipt> {
 
-             const provider = getProvider(this.runner);
 
-             assert(provider, "contract runner does not have a provider",
 
-                 "UNSUPPORTED_OPERATION", { operation: "queryTransaction" });
 
-             const receipt = await provider.getTransactionReceipt(hash);
 
-             if (receipt == null) { return null; }
 
-             return new ContractTransactionReceipt(this.interface, provider, receipt);
 
-         }
 
-         */
 
-         /**
 
-          *  Provide historic access to event data for %%event%% in the range
 
-          *  %%fromBlock%% (default: ``0``) to %%toBlock%% (default: ``"latest"``)
 
-          *  inclusive.
 
-          */
 
-         async queryFilter(event, fromBlock, toBlock) {
 
-             if (fromBlock == null) {
 
-                 fromBlock = 0;
 
-             }
 
-             if (toBlock == null) {
 
-                 toBlock = "latest";
 
-             }
 
-             const { addr, addrPromise } = getInternal(this);
 
-             const address = (addr ? addr : (await addrPromise));
 
-             const { fragment, topics } = await getSubInfo(this, event);
 
-             const filter = { address, topics, fromBlock, toBlock };
 
-             const provider = getProvider(this.runner);
 
-             assert(provider, "contract runner does not have a provider", "UNSUPPORTED_OPERATION", { operation: "queryFilter" });
 
-             return (await provider.getLogs(filter)).map((log) => {
 
-                 let foundFragment = fragment;
 
-                 if (foundFragment == null) {
 
-                     try {
 
-                         foundFragment = this.interface.getEvent(log.topics[0]);
 
-                     }
 
-                     catch (error) { }
 
-                 }
 
-                 if (foundFragment) {
 
-                     try {
 
-                         return new EventLog(log, this.interface, foundFragment);
 
-                     }
 
-                     catch (error) {
 
-                         return new UndecodedEventLog(log, error);
 
-                     }
 
-                 }
 
-                 return new Log(log, provider);
 
-             });
 
-         }
 
-         /**
 
-          *  Add an event %%listener%% for the %%event%%.
 
-          */
 
-         async on(event, listener) {
 
-             const sub = await getSub(this, "on", event);
 
-             sub.listeners.push({ listener, once: false });
 
-             sub.start();
 
-             return this;
 
-         }
 
-         /**
 
-          *  Add an event %%listener%% for the %%event%%, but remove the listener
 
-          *  after it is fired once.
 
-          */
 
-         async once(event, listener) {
 
-             const sub = await getSub(this, "once", event);
 
-             sub.listeners.push({ listener, once: true });
 
-             sub.start();
 
-             return this;
 
-         }
 
-         /**
 
-          *  Emit an %%event%% calling all listeners with %%args%%.
 
-          *
 
-          *  Resolves to ``true`` if any listeners were called.
 
-          */
 
-         async emit(event, ...args) {
 
-             return await emit(this, event, args, null);
 
-         }
 
-         /**
 
-          *  Resolves to the number of listeners of %%event%% or the total number
 
-          *  of listeners if unspecified.
 
-          */
 
-         async listenerCount(event) {
 
-             if (event) {
 
-                 const sub = await hasSub(this, event);
 
-                 if (!sub) {
 
-                     return 0;
 
-                 }
 
-                 return sub.listeners.length;
 
-             }
 
-             const { subs } = getInternal(this);
 
-             let total = 0;
 
-             for (const { listeners } of subs.values()) {
 
-                 total += listeners.length;
 
-             }
 
-             return total;
 
-         }
 
-         /**
 
-          *  Resolves to the listeners subscribed to %%event%% or all listeners
 
-          *  if unspecified.
 
-          */
 
-         async listeners(event) {
 
-             if (event) {
 
-                 const sub = await hasSub(this, event);
 
-                 if (!sub) {
 
-                     return [];
 
-                 }
 
-                 return sub.listeners.map(({ listener }) => listener);
 
-             }
 
-             const { subs } = getInternal(this);
 
-             let result = [];
 
-             for (const { listeners } of subs.values()) {
 
-                 result = result.concat(listeners.map(({ listener }) => listener));
 
-             }
 
-             return result;
 
-         }
 
-         /**
 
-          *  Remove the %%listener%% from the listeners for %%event%% or remove
 
-          *  all listeners if unspecified.
 
-          */
 
-         async off(event, listener) {
 
-             const sub = await hasSub(this, event);
 
-             if (!sub) {
 
-                 return this;
 
-             }
 
-             if (listener) {
 
-                 const index = sub.listeners.map(({ listener }) => listener).indexOf(listener);
 
-                 if (index >= 0) {
 
-                     sub.listeners.splice(index, 1);
 
-                 }
 
-             }
 
-             if (listener == null || sub.listeners.length === 0) {
 
-                 sub.stop();
 
-                 getInternal(this).subs.delete(sub.tag);
 
-             }
 
-             return this;
 
-         }
 
-         /**
 
-          *  Remove all the listeners for %%event%% or remove all listeners if
 
-          *  unspecified.
 
-          */
 
-         async removeAllListeners(event) {
 
-             if (event) {
 
-                 const sub = await hasSub(this, event);
 
-                 if (!sub) {
 
-                     return this;
 
-                 }
 
-                 sub.stop();
 
-                 getInternal(this).subs.delete(sub.tag);
 
-             }
 
-             else {
 
-                 const { subs } = getInternal(this);
 
-                 for (const { tag, stop } of subs.values()) {
 
-                     stop();
 
-                     subs.delete(tag);
 
-                 }
 
-             }
 
-             return this;
 
-         }
 
-         /**
 
-          *  Alias for [on].
 
-          */
 
-         async addListener(event, listener) {
 
-             return await this.on(event, listener);
 
-         }
 
-         /**
 
-          *  Alias for [off].
 
-          */
 
-         async removeListener(event, listener) {
 
-             return await this.off(event, listener);
 
-         }
 
-         /**
 
-          *  Create a new Class for the %%abi%%.
 
-          */
 
-         static buildClass(abi) {
 
-             class CustomContract extends BaseContract {
 
-                 constructor(address, runner = null) {
 
-                     super(address, abi, runner);
 
-                 }
 
-             }
 
-             return CustomContract;
 
-         }
 
-         ;
 
-         /**
 
-          *  Create a new BaseContract with a specified Interface.
 
-          */
 
-         static from(target, abi, runner) {
 
-             if (runner == null) {
 
-                 runner = null;
 
-             }
 
-             const contract = new this(target, abi, runner);
 
-             return contract;
 
-         }
 
-     }
 
-     function _ContractBase() {
 
-         return BaseContract;
 
-     }
 
-     /**
 
-      *  A [[BaseContract]] with no type guards on its methods or events.
 
-      */
 
-     class Contract extends _ContractBase() {
 
-     }
 
-     // A = Arguments to the constructor
 
-     // I = Interface of deployed contracts
 
-     /**
 
-      *  A **ContractFactory** is used to deploy a Contract to the blockchain.
 
-      */
 
-     class ContractFactory {
 
-         /**
 
-          *  The Contract Interface.
 
-          */
 
-         interface;
 
-         /**
 
-          *  The Contract deployment bytecode. Often called the initcode.
 
-          */
 
-         bytecode;
 
-         /**
 
-          *  The ContractRunner to deploy the Contract as.
 
-          */
 
-         runner;
 
-         /**
 
-          *  Create a new **ContractFactory** with %%abi%% and %%bytecode%%,
 
-          *  optionally connected to %%runner%%.
 
-          *
 
-          *  The %%bytecode%% may be the ``bytecode`` property within the
 
-          *  standard Solidity JSON output.
 
-          */
 
-         constructor(abi, bytecode, runner) {
 
-             const iface = Interface.from(abi);
 
-             // Dereference Solidity bytecode objects and allow a missing `0x`-prefix
 
-             if (bytecode instanceof Uint8Array) {
 
-                 bytecode = hexlify(getBytes(bytecode));
 
-             }
 
-             else {
 
-                 if (typeof (bytecode) === "object") {
 
-                     bytecode = bytecode.object;
 
-                 }
 
-                 if (!bytecode.startsWith("0x")) {
 
-                     bytecode = "0x" + bytecode;
 
-                 }
 
-                 bytecode = hexlify(getBytes(bytecode));
 
-             }
 
-             defineProperties(this, {
 
-                 bytecode, interface: iface, runner: (runner || null)
 
-             });
 
-         }
 
-         attach(target) {
 
-             return new BaseContract(target, this.interface, this.runner);
 
-         }
 
-         /**
 
-          *  Resolves to the transaction to deploy the contract, passing %%args%%
 
-          *  into the constructor.
 
-          */
 
-         async getDeployTransaction(...args) {
 
-             let overrides = {};
 
-             const fragment = this.interface.deploy;
 
-             if (fragment.inputs.length + 1 === args.length) {
 
-                 overrides = await copyOverrides(args.pop());
 
-             }
 
-             if (fragment.inputs.length !== args.length) {
 
-                 throw new Error("incorrect number of arguments to constructor");
 
-             }
 
-             const resolvedArgs = await resolveArgs(this.runner, fragment.inputs, args);
 
-             const data = concat([this.bytecode, this.interface.encodeDeploy(resolvedArgs)]);
 
-             return Object.assign({}, overrides, { data });
 
-         }
 
-         /**
 
-          *  Resolves to the Contract deployed by passing %%args%% into the
 
-          *  constructor.
 
-          *
 
-          *  This will resolve to the Contract before it has been deployed to the
 
-          *  network, so the [[BaseContract-waitForDeployment]] should be used before
 
-          *  sending any transactions to it.
 
-          */
 
-         async deploy(...args) {
 
-             const tx = await this.getDeployTransaction(...args);
 
-             assert(this.runner && typeof (this.runner.sendTransaction) === "function", "factory runner does not support sending transactions", "UNSUPPORTED_OPERATION", {
 
-                 operation: "sendTransaction"
 
-             });
 
-             const sentTx = await this.runner.sendTransaction(tx);
 
-             const address = getCreateAddress(sentTx);
 
-             return new BaseContract(address, this.interface, this.runner, sentTx);
 
-         }
 
-         /**
 
-          *  Return a new **ContractFactory** with the same ABI and bytecode,
 
-          *  but connected to %%runner%%.
 
-          */
 
-         connect(runner) {
 
-             return new ContractFactory(this.interface, this.bytecode, runner);
 
-         }
 
-         /**
 
-          *  Create a new **ContractFactory** from the standard Solidity JSON output.
 
-          */
 
-         static fromSolidity(output, runner) {
 
-             assertArgument(output != null, "bad compiler output", "output", output);
 
-             if (typeof (output) === "string") {
 
-                 output = JSON.parse(output);
 
-             }
 
-             const abi = output.abi;
 
-             let bytecode = "";
 
-             if (output.bytecode) {
 
-                 bytecode = output.bytecode;
 
-             }
 
-             else if (output.evm && output.evm.bytecode) {
 
-                 bytecode = output.evm.bytecode;
 
-             }
 
-             return new this(abi, bytecode, runner);
 
-         }
 
-     }
 
-     /**
 
-      *  ENS is a service which allows easy-to-remember names to map to
 
-      *  network addresses.
 
-      *
 
-      *  @_section: api/providers/ens-resolver:ENS Resolver  [about-ens-rsolver]
 
-      */
 
-     // @TODO: This should use the fetch-data:ipfs gateway
 
-     // Trim off the ipfs:// prefix and return the default gateway URL
 
-     function getIpfsLink(link) {
 
-         if (link.match(/^ipfs:\/\/ipfs\//i)) {
 
-             link = link.substring(12);
 
-         }
 
-         else if (link.match(/^ipfs:\/\//i)) {
 
-             link = link.substring(7);
 
-         }
 
-         else {
 
-             assertArgument(false, "unsupported IPFS format", "link", link);
 
-         }
 
-         return `https:/\/gateway.ipfs.io/ipfs/${link}`;
 
-     }
 
-     /**
 
-      *  A provider plugin super-class for processing multicoin address types.
 
-      */
 
-     class MulticoinProviderPlugin {
 
-         /**
 
-          *  The name.
 
-          */
 
-         name;
 
-         /**
 
-          *  Creates a new **MulticoinProviderPluing** for %%name%%.
 
-          */
 
-         constructor(name) {
 
-             defineProperties(this, { name });
 
-         }
 
-         connect(proivder) {
 
-             return this;
 
-         }
 
-         /**
 
-          *  Returns ``true`` if %%coinType%% is supported by this plugin.
 
-          */
 
-         supportsCoinType(coinType) {
 
-             return false;
 
-         }
 
-         /**
 
-          *  Resolves to the encoded %%address%% for %%coinType%%.
 
-          */
 
-         async encodeAddress(coinType, address) {
 
-             throw new Error("unsupported coin");
 
-         }
 
-         /**
 
-          *  Resolves to the decoded %%data%% for %%coinType%%.
 
-          */
 
-         async decodeAddress(coinType, data) {
 
-             throw new Error("unsupported coin");
 
-         }
 
-     }
 
-     const matcherIpfs = new RegExp("^(ipfs):/\/(.*)$", "i");
 
-     const matchers = [
 
-         new RegExp("^(https):/\/(.*)$", "i"),
 
-         new RegExp("^(data):(.*)$", "i"),
 
-         matcherIpfs,
 
-         new RegExp("^eip155:[0-9]+/(erc[0-9]+):(.*)$", "i"),
 
-     ];
 
-     /**
 
-      *  A connected object to a resolved ENS name resolver, which can be
 
-      *  used to query additional details.
 
-      */
 
-     class EnsResolver {
 
-         /**
 
-          *  The connected provider.
 
-          */
 
-         provider;
 
-         /**
 
-          *  The address of the resolver.
 
-          */
 
-         address;
 
-         /**
 
-          *  The name this resolver was resolved against.
 
-          */
 
-         name;
 
-         // For EIP-2544 names, the ancestor that provided the resolver
 
-         #supports2544;
 
-         #resolver;
 
-         constructor(provider, address, name) {
 
-             defineProperties(this, { provider, address, name });
 
-             this.#supports2544 = null;
 
-             this.#resolver = new Contract(address, [
 
-                 "function supportsInterface(bytes4) view returns (bool)",
 
-                 "function resolve(bytes, bytes) view returns (bytes)",
 
-                 "function addr(bytes32) view returns (address)",
 
-                 "function addr(bytes32, uint) view returns (bytes)",
 
-                 "function text(bytes32, string) view returns (string)",
 
-                 "function contenthash(bytes32) view returns (bytes)",
 
-             ], provider);
 
-         }
 
-         /**
 
-          *  Resolves to true if the resolver supports wildcard resolution.
 
-          */
 
-         async supportsWildcard() {
 
-             if (this.#supports2544 == null) {
 
-                 this.#supports2544 = (async () => {
 
-                     try {
 
-                         return await this.#resolver.supportsInterface("0x9061b923");
 
-                     }
 
-                     catch (error) {
 
-                         // Wildcard resolvers must understand supportsInterface
 
-                         // and return true.
 
-                         if (isError(error, "CALL_EXCEPTION")) {
 
-                             return false;
 
-                         }
 
-                         // Let future attempts try again...
 
-                         this.#supports2544 = null;
 
-                         throw error;
 
-                     }
 
-                 })();
 
-             }
 
-             return await this.#supports2544;
 
-         }
 
-         async #fetch(funcName, params) {
 
-             params = (params || []).slice();
 
-             const iface = this.#resolver.interface;
 
-             // The first parameters is always the nodehash
 
-             params.unshift(namehash(this.name));
 
-             let fragment = null;
 
-             if (await this.supportsWildcard()) {
 
-                 fragment = iface.getFunction(funcName);
 
-                 assert(fragment, "missing fragment", "UNKNOWN_ERROR", {
 
-                     info: { funcName }
 
-                 });
 
-                 params = [
 
-                     dnsEncode(this.name, 255),
 
-                     iface.encodeFunctionData(fragment, params)
 
-                 ];
 
-                 funcName = "resolve(bytes,bytes)";
 
-             }
 
-             params.push({
 
-                 enableCcipRead: true
 
-             });
 
-             try {
 
-                 const result = await this.#resolver[funcName](...params);
 
-                 if (fragment) {
 
-                     return iface.decodeFunctionResult(fragment, result)[0];
 
-                 }
 
-                 return result;
 
-             }
 
-             catch (error) {
 
-                 if (!isError(error, "CALL_EXCEPTION")) {
 
-                     throw error;
 
-                 }
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  Resolves to the address for %%coinType%% or null if the
 
-          *  provided %%coinType%% has not been configured.
 
-          */
 
-         async getAddress(coinType) {
 
-             if (coinType == null) {
 
-                 coinType = 60;
 
-             }
 
-             if (coinType === 60) {
 
-                 try {
 
-                     const result = await this.#fetch("addr(bytes32)");
 
-                     // No address
 
-                     if (result == null || result === ZeroAddress) {
 
-                         return null;
 
-                     }
 
-                     return result;
 
-                 }
 
-                 catch (error) {
 
-                     if (isError(error, "CALL_EXCEPTION")) {
 
-                         return null;
 
-                     }
 
-                     throw error;
 
-                 }
 
-             }
 
-             // Try decoding its EVM canonical chain as an EVM chain address first
 
-             if (coinType >= 0 && coinType < 0x80000000) {
 
-                 let ethCoinType = coinType + 0x80000000;
 
-                 const data = await this.#fetch("addr(bytes32,uint)", [ethCoinType]);
 
-                 if (isHexString(data, 20)) {
 
-                     return getAddress(data);
 
-                 }
 
-             }
 
-             let coinPlugin = null;
 
-             for (const plugin of this.provider.plugins) {
 
-                 if (!(plugin instanceof MulticoinProviderPlugin)) {
 
-                     continue;
 
-                 }
 
-                 if (plugin.supportsCoinType(coinType)) {
 
-                     coinPlugin = plugin;
 
-                     break;
 
-                 }
 
-             }
 
-             if (coinPlugin == null) {
 
-                 return null;
 
-             }
 
-             // keccak256("addr(bytes32,uint256")
 
-             const data = await this.#fetch("addr(bytes32,uint)", [coinType]);
 
-             // No address
 
-             if (data == null || data === "0x") {
 
-                 return null;
 
-             }
 
-             // Compute the address
 
-             const address = await coinPlugin.decodeAddress(coinType, data);
 
-             if (address != null) {
 
-                 return address;
 
-             }
 
-             assert(false, `invalid coin data`, "UNSUPPORTED_OPERATION", {
 
-                 operation: `getAddress(${coinType})`,
 
-                 info: { coinType, data }
 
-             });
 
-         }
 
-         /**
 
-          *  Resolves to the EIP-634 text record for %%key%%, or ``null``
 
-          *  if unconfigured.
 
-          */
 
-         async getText(key) {
 
-             const data = await this.#fetch("text(bytes32,string)", [key]);
 
-             if (data == null || data === "0x") {
 
-                 return null;
 
-             }
 
-             return data;
 
-         }
 
-         /**
 
-          *  Rsolves to the content-hash or ``null`` if unconfigured.
 
-          */
 
-         async getContentHash() {
 
-             // keccak256("contenthash()")
 
-             const data = await this.#fetch("contenthash(bytes32)");
 
-             // No contenthash
 
-             if (data == null || data === "0x") {
 
-                 return null;
 
-             }
 
-             // IPFS (CID: 1, Type: 70=DAG-PB, 72=libp2p-key)
 
-             const ipfs = data.match(/^0x(e3010170|e5010172)(([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f]*))$/);
 
-             if (ipfs) {
 
-                 const scheme = (ipfs[1] === "e3010170") ? "ipfs" : "ipns";
 
-                 const length = parseInt(ipfs[4], 16);
 
-                 if (ipfs[5].length === length * 2) {
 
-                     return `${scheme}:/\/${encodeBase58("0x" + ipfs[2])}`;
 
-                 }
 
-             }
 
-             // Swarm (CID: 1, Type: swarm-manifest; hash/length hard-coded to keccak256/32)
 
-             const swarm = data.match(/^0xe40101fa011b20([0-9a-f]*)$/);
 
-             if (swarm && swarm[1].length === 64) {
 
-                 return `bzz:/\/${swarm[1]}`;
 
-             }
 
-             assert(false, `invalid or unsupported content hash data`, "UNSUPPORTED_OPERATION", {
 
-                 operation: "getContentHash()",
 
-                 info: { data }
 
-             });
 
-         }
 
-         /**
 
-          *  Resolves to the avatar url or ``null`` if the avatar is either
 
-          *  unconfigured or incorrectly configured (e.g. references an NFT
 
-          *  not owned by the address).
 
-          *
 
-          *  If diagnosing issues with configurations, the [[_getAvatar]]
 
-          *  method may be useful.
 
-          */
 
-         async getAvatar() {
 
-             const avatar = await this._getAvatar();
 
-             return avatar.url;
 
-         }
 
-         /**
 
-          *  When resolving an avatar, there are many steps involved, such
 
-          *  fetching metadata and possibly validating ownership of an
 
-          *  NFT.
 
-          *
 
-          *  This method can be used to examine each step and the value it
 
-          *  was working from.
 
-          */
 
-         async _getAvatar() {
 
-             const linkage = [{ type: "name", value: this.name }];
 
-             try {
 
-                 // test data for ricmoo.eth
 
-                 //const avatar = "eip155:1/erc721:0x265385c7f4132228A0d54EB1A9e7460b91c0cC68/29233";
 
-                 const avatar = await this.getText("avatar");
 
-                 if (avatar == null) {
 
-                     linkage.push({ type: "!avatar", value: "" });
 
-                     return { url: null, linkage };
 
-                 }
 
-                 linkage.push({ type: "avatar", value: avatar });
 
-                 for (let i = 0; i < matchers.length; i++) {
 
-                     const match = avatar.match(matchers[i]);
 
-                     if (match == null) {
 
-                         continue;
 
-                     }
 
-                     const scheme = match[1].toLowerCase();
 
-                     switch (scheme) {
 
-                         case "https":
 
-                         case "data":
 
-                             linkage.push({ type: "url", value: avatar });
 
-                             return { linkage, url: avatar };
 
-                         case "ipfs": {
 
-                             const url = getIpfsLink(avatar);
 
-                             linkage.push({ type: "ipfs", value: avatar });
 
-                             linkage.push({ type: "url", value: url });
 
-                             return { linkage, url };
 
-                         }
 
-                         case "erc721":
 
-                         case "erc1155": {
 
-                             // Depending on the ERC type, use tokenURI(uint256) or url(uint256)
 
-                             const selector = (scheme === "erc721") ? "tokenURI(uint256)" : "uri(uint256)";
 
-                             linkage.push({ type: scheme, value: avatar });
 
-                             // The owner of this name
 
-                             const owner = await this.getAddress();
 
-                             if (owner == null) {
 
-                                 linkage.push({ type: "!owner", value: "" });
 
-                                 return { url: null, linkage };
 
-                             }
 
-                             const comps = (match[2] || "").split("/");
 
-                             if (comps.length !== 2) {
 
-                                 linkage.push({ type: `!${scheme}caip`, value: (match[2] || "") });
 
-                                 return { url: null, linkage };
 
-                             }
 
-                             const tokenId = comps[1];
 
-                             const contract = new Contract(comps[0], [
 
-                                 // ERC-721
 
-                                 "function tokenURI(uint) view returns (string)",
 
-                                 "function ownerOf(uint) view returns (address)",
 
-                                 // ERC-1155
 
-                                 "function uri(uint) view returns (string)",
 
-                                 "function balanceOf(address, uint256) view returns (uint)"
 
-                             ], this.provider);
 
-                             // Check that this account owns the token
 
-                             if (scheme === "erc721") {
 
-                                 const tokenOwner = await contract.ownerOf(tokenId);
 
-                                 if (owner !== tokenOwner) {
 
-                                     linkage.push({ type: "!owner", value: tokenOwner });
 
-                                     return { url: null, linkage };
 
-                                 }
 
-                                 linkage.push({ type: "owner", value: tokenOwner });
 
-                             }
 
-                             else if (scheme === "erc1155") {
 
-                                 const balance = await contract.balanceOf(owner, tokenId);
 
-                                 if (!balance) {
 
-                                     linkage.push({ type: "!balance", value: "0" });
 
-                                     return { url: null, linkage };
 
-                                 }
 
-                                 linkage.push({ type: "balance", value: balance.toString() });
 
-                             }
 
-                             // Call the token contract for the metadata URL
 
-                             let metadataUrl = await contract[selector](tokenId);
 
-                             if (metadataUrl == null || metadataUrl === "0x") {
 
-                                 linkage.push({ type: "!metadata-url", value: "" });
 
-                                 return { url: null, linkage };
 
-                             }
 
-                             linkage.push({ type: "metadata-url-base", value: metadataUrl });
 
-                             // ERC-1155 allows a generic {id} in the URL
 
-                             if (scheme === "erc1155") {
 
-                                 metadataUrl = metadataUrl.replace("{id}", toBeHex(tokenId, 32).substring(2));
 
-                                 linkage.push({ type: "metadata-url-expanded", value: metadataUrl });
 
-                             }
 
-                             // Transform IPFS metadata links
 
-                             if (metadataUrl.match(/^ipfs:/i)) {
 
-                                 metadataUrl = getIpfsLink(metadataUrl);
 
-                             }
 
-                             linkage.push({ type: "metadata-url", value: metadataUrl });
 
-                             // Get the token metadata
 
-                             let metadata = {};
 
-                             const response = await (new FetchRequest(metadataUrl)).send();
 
-                             response.assertOk();
 
-                             try {
 
-                                 metadata = response.bodyJson;
 
-                             }
 
-                             catch (error) {
 
-                                 try {
 
-                                     linkage.push({ type: "!metadata", value: response.bodyText });
 
-                                 }
 
-                                 catch (error) {
 
-                                     const bytes = response.body;
 
-                                     if (bytes) {
 
-                                         linkage.push({ type: "!metadata", value: hexlify(bytes) });
 
-                                     }
 
-                                     return { url: null, linkage };
 
-                                 }
 
-                                 return { url: null, linkage };
 
-                             }
 
-                             if (!metadata) {
 
-                                 linkage.push({ type: "!metadata", value: "" });
 
-                                 return { url: null, linkage };
 
-                             }
 
-                             linkage.push({ type: "metadata", value: JSON.stringify(metadata) });
 
-                             // Pull the image URL out
 
-                             let imageUrl = metadata.image;
 
-                             if (typeof (imageUrl) !== "string") {
 
-                                 linkage.push({ type: "!imageUrl", value: "" });
 
-                                 return { url: null, linkage };
 
-                             }
 
-                             if (imageUrl.match(/^(https:\/\/|data:)/i)) {
 
-                                 // Allow
 
-                             }
 
-                             else {
 
-                                 // Transform IPFS link to gateway
 
-                                 const ipfs = imageUrl.match(matcherIpfs);
 
-                                 if (ipfs == null) {
 
-                                     linkage.push({ type: "!imageUrl-ipfs", value: imageUrl });
 
-                                     return { url: null, linkage };
 
-                                 }
 
-                                 linkage.push({ type: "imageUrl-ipfs", value: imageUrl });
 
-                                 imageUrl = getIpfsLink(imageUrl);
 
-                             }
 
-                             linkage.push({ type: "url", value: imageUrl });
 
-                             return { linkage, url: imageUrl };
 
-                         }
 
-                     }
 
-                 }
 
-             }
 
-             catch (error) { }
 
-             return { linkage, url: null };
 
-         }
 
-         static async getEnsAddress(provider) {
 
-             const network = await provider.getNetwork();
 
-             const ensPlugin = network.getPlugin("org.ethers.plugins.network.Ens");
 
-             // No ENS...
 
-             assert(ensPlugin, "network does not support ENS", "UNSUPPORTED_OPERATION", {
 
-                 operation: "getEnsAddress", info: { network }
 
-             });
 
-             return ensPlugin.address;
 
-         }
 
-         static async #getResolver(provider, name) {
 
-             const ensAddr = await EnsResolver.getEnsAddress(provider);
 
-             try {
 
-                 const contract = new Contract(ensAddr, [
 
-                     "function resolver(bytes32) view returns (address)"
 
-                 ], provider);
 
-                 const addr = await contract.resolver(namehash(name), {
 
-                     enableCcipRead: true
 
-                 });
 
-                 if (addr === ZeroAddress) {
 
-                     return null;
 
-                 }
 
-                 return addr;
 
-             }
 
-             catch (error) {
 
-                 // ENS registry cannot throw errors on resolver(bytes32),
 
-                 // so probably a link error
 
-                 throw error;
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  Resolve to the ENS resolver for %%name%% using %%provider%% or
 
-          *  ``null`` if unconfigured.
 
-          */
 
-         static async fromName(provider, name) {
 
-             let currentName = name;
 
-             while (true) {
 
-                 if (currentName === "" || currentName === ".") {
 
-                     return null;
 
-                 }
 
-                 // Optimization since the eth node cannot change and does
 
-                 // not have a wildcard resolver
 
-                 if (name !== "eth" && currentName === "eth") {
 
-                     return null;
 
-                 }
 
-                 // Check the current node for a resolver
 
-                 const addr = await EnsResolver.#getResolver(provider, currentName);
 
-                 // Found a resolver!
 
-                 if (addr != null) {
 
-                     const resolver = new EnsResolver(provider, addr, name);
 
-                     // Legacy resolver found, using EIP-2544 so it isn't safe to use
 
-                     if (currentName !== name && !(await resolver.supportsWildcard())) {
 
-                         return null;
 
-                     }
 
-                     return resolver;
 
-                 }
 
-                 // Get the parent node
 
-                 currentName = currentName.split(".").slice(1).join(".");
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     const BN_0 = BigInt(0);
 
-     function allowNull(format, nullValue) {
 
-         return (function (value) {
 
-             if (value == null) {
 
-                 return nullValue;
 
-             }
 
-             return format(value);
 
-         });
 
-     }
 
-     function arrayOf(format, allowNull) {
 
-         return ((array) => {
 
-             if (allowNull && array == null) {
 
-                 return null;
 
-             }
 
-             if (!Array.isArray(array)) {
 
-                 throw new Error("not an array");
 
-             }
 
-             return array.map((i) => format(i));
 
-         });
 
-     }
 
-     // Requires an object which matches a fleet of other formatters
 
-     // Any FormatFunc may return `undefined` to have the value omitted
 
-     // from the result object. Calls preserve `this`.
 
-     function object(format, altNames) {
 
-         return ((value) => {
 
-             const result = {};
 
-             for (const key in format) {
 
-                 let srcKey = key;
 
-                 if (altNames && key in altNames && !(srcKey in value)) {
 
-                     for (const altKey of altNames[key]) {
 
-                         if (altKey in value) {
 
-                             srcKey = altKey;
 
-                             break;
 
-                         }
 
-                     }
 
-                 }
 
-                 try {
 
-                     const nv = format[key](value[srcKey]);
 
-                     if (nv !== undefined) {
 
-                         result[key] = nv;
 
-                     }
 
-                 }
 
-                 catch (error) {
 
-                     const message = (error instanceof Error) ? error.message : "not-an-error";
 
-                     assert(false, `invalid value for value.${key} (${message})`, "BAD_DATA", { value });
 
-                 }
 
-             }
 
-             return result;
 
-         });
 
-     }
 
-     function formatBoolean(value) {
 
-         switch (value) {
 
-             case true:
 
-             case "true":
 
-                 return true;
 
-             case false:
 
-             case "false":
 
-                 return false;
 
-         }
 
-         assertArgument(false, `invalid boolean; ${JSON.stringify(value)}`, "value", value);
 
-     }
 
-     function formatData(value) {
 
-         assertArgument(isHexString(value, true), "invalid data", "value", value);
 
-         return value;
 
-     }
 
-     function formatHash(value) {
 
-         assertArgument(isHexString(value, 32), "invalid hash", "value", value);
 
-         return value;
 
-     }
 
-     const _formatLog = object({
 
-         address: getAddress,
 
-         blockHash: formatHash,
 
-         blockNumber: getNumber,
 
-         data: formatData,
 
-         index: getNumber,
 
-         removed: allowNull(formatBoolean, false),
 
-         topics: arrayOf(formatHash),
 
-         transactionHash: formatHash,
 
-         transactionIndex: getNumber,
 
-     }, {
 
-         index: ["logIndex"]
 
-     });
 
-     function formatLog(value) {
 
-         return _formatLog(value);
 
-     }
 
-     const _formatBlock = object({
 
-         hash: allowNull(formatHash),
 
-         parentHash: formatHash,
 
-         parentBeaconBlockRoot: allowNull(formatHash, null),
 
-         number: getNumber,
 
-         timestamp: getNumber,
 
-         nonce: allowNull(formatData),
 
-         difficulty: getBigInt,
 
-         gasLimit: getBigInt,
 
-         gasUsed: getBigInt,
 
-         stateRoot: allowNull(formatHash, null),
 
-         receiptsRoot: allowNull(formatHash, null),
 
-         blobGasUsed: allowNull(getBigInt, null),
 
-         excessBlobGas: allowNull(getBigInt, null),
 
-         miner: allowNull(getAddress),
 
-         prevRandao: allowNull(formatHash, null),
 
-         extraData: formatData,
 
-         baseFeePerGas: allowNull(getBigInt)
 
-     }, {
 
-         prevRandao: ["mixHash"]
 
-     });
 
-     function formatBlock(value) {
 
-         const result = _formatBlock(value);
 
-         result.transactions = value.transactions.map((tx) => {
 
-             if (typeof (tx) === "string") {
 
-                 return tx;
 
-             }
 
-             return formatTransactionResponse(tx);
 
-         });
 
-         return result;
 
-     }
 
-     const _formatReceiptLog = object({
 
-         transactionIndex: getNumber,
 
-         blockNumber: getNumber,
 
-         transactionHash: formatHash,
 
-         address: getAddress,
 
-         topics: arrayOf(formatHash),
 
-         data: formatData,
 
-         index: getNumber,
 
-         blockHash: formatHash,
 
-     }, {
 
-         index: ["logIndex"]
 
-     });
 
-     function formatReceiptLog(value) {
 
-         return _formatReceiptLog(value);
 
-     }
 
-     const _formatTransactionReceipt = object({
 
-         to: allowNull(getAddress, null),
 
-         from: allowNull(getAddress, null),
 
-         contractAddress: allowNull(getAddress, null),
 
-         // should be allowNull(hash), but broken-EIP-658 support is handled in receipt
 
-         index: getNumber,
 
-         root: allowNull(hexlify),
 
-         gasUsed: getBigInt,
 
-         blobGasUsed: allowNull(getBigInt, null),
 
-         logsBloom: allowNull(formatData),
 
-         blockHash: formatHash,
 
-         hash: formatHash,
 
-         logs: arrayOf(formatReceiptLog),
 
-         blockNumber: getNumber,
 
-         //confirmations: allowNull(getNumber, null),
 
-         cumulativeGasUsed: getBigInt,
 
-         effectiveGasPrice: allowNull(getBigInt),
 
-         blobGasPrice: allowNull(getBigInt, null),
 
-         status: allowNull(getNumber),
 
-         type: allowNull(getNumber, 0)
 
-     }, {
 
-         effectiveGasPrice: ["gasPrice"],
 
-         hash: ["transactionHash"],
 
-         index: ["transactionIndex"],
 
-     });
 
-     function formatTransactionReceipt(value) {
 
-         return _formatTransactionReceipt(value);
 
-     }
 
-     function formatTransactionResponse(value) {
 
-         // Some clients (TestRPC) do strange things like return 0x0 for the
 
-         // 0 address; correct this to be a real address
 
-         if (value.to && getBigInt(value.to) === BN_0) {
 
-             value.to = "0x0000000000000000000000000000000000000000";
 
-         }
 
-         const result = object({
 
-             hash: formatHash,
 
-             // Some nodes do not return this, usually test nodes (like Ganache)
 
-             index: allowNull(getNumber, undefined),
 
-             type: (value) => {
 
-                 if (value === "0x" || value == null) {
 
-                     return 0;
 
-                 }
 
-                 return getNumber(value);
 
-             },
 
-             accessList: allowNull(accessListify, null),
 
-             blobVersionedHashes: allowNull(arrayOf(formatHash, true), null),
 
-             blockHash: allowNull(formatHash, null),
 
-             blockNumber: allowNull(getNumber, null),
 
-             transactionIndex: allowNull(getNumber, null),
 
-             from: getAddress,
 
-             // either (gasPrice) or (maxPriorityFeePerGas + maxFeePerGas) must be set
 
-             gasPrice: allowNull(getBigInt),
 
-             maxPriorityFeePerGas: allowNull(getBigInt),
 
-             maxFeePerGas: allowNull(getBigInt),
 
-             maxFeePerBlobGas: allowNull(getBigInt, null),
 
-             gasLimit: getBigInt,
 
-             to: allowNull(getAddress, null),
 
-             value: getBigInt,
 
-             nonce: getNumber,
 
-             data: formatData,
 
-             creates: allowNull(getAddress, null),
 
-             chainId: allowNull(getBigInt, null)
 
-         }, {
 
-             data: ["input"],
 
-             gasLimit: ["gas"],
 
-             index: ["transactionIndex"]
 
-         })(value);
 
-         // If to and creates are empty, populate the creates from the value
 
-         if (result.to == null && result.creates == null) {
 
-             result.creates = getCreateAddress(result);
 
-         }
 
-         // @TODO: Check fee data
 
-         // Add an access list to supported transaction types
 
-         if ((value.type === 1 || value.type === 2) && value.accessList == null) {
 
-             result.accessList = [];
 
-         }
 
-         // Compute the signature
 
-         if (value.signature) {
 
-             result.signature = Signature.from(value.signature);
 
-         }
 
-         else {
 
-             result.signature = Signature.from(value);
 
-         }
 
-         // Some backends omit ChainId on legacy transactions, but we can compute it
 
-         if (result.chainId == null) {
 
-             const chainId = result.signature.legacyChainId;
 
-             if (chainId != null) {
 
-                 result.chainId = chainId;
 
-             }
 
-         }
 
-         // @TODO: check chainID
 
-         /*
 
-         if (value.chainId != null) {
 
-             let chainId = value.chainId;
 
-             if (isHexString(chainId)) {
 
-                 chainId = BigNumber.from(chainId).toNumber();
 
-             }
 
-             result.chainId = chainId;
 
-         } else {
 
-             let chainId = value.networkId;
 
-             // geth-etc returns chainId
 
-             if (chainId == null && result.v == null) {
 
-                 chainId = value.chainId;
 
-             }
 
-             if (isHexString(chainId)) {
 
-                 chainId = BigNumber.from(chainId).toNumber();
 
-             }
 
-             if (typeof(chainId) !== "number" && result.v != null) {
 
-                 chainId = (result.v - 35) / 2;
 
-                 if (chainId < 0) { chainId = 0; }
 
-                 chainId = parseInt(chainId);
 
-             }
 
-             if (typeof(chainId) !== "number") { chainId = 0; }
 
-             result.chainId = chainId;
 
-         }
 
-         */
 
-         // 0x0000... should actually be null
 
-         if (result.blockHash && getBigInt(result.blockHash) === BN_0) {
 
-             result.blockHash = null;
 
-         }
 
-         return result;
 
-     }
 
-     const EnsAddress = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
 
-     /**
 
-      *  A **NetworkPlugin** provides additional functionality on a [[Network]].
 
-      */
 
-     class NetworkPlugin {
 
-         /**
 
-          *  The name of the plugin.
 
-          *
 
-          *  It is recommended to use reverse-domain-notation, which permits
 
-          *  unique names with a known authority as well as hierarchal entries.
 
-          */
 
-         name;
 
-         /**
 
-          *  Creates a new **NetworkPlugin**.
 
-          */
 
-         constructor(name) {
 
-             defineProperties(this, { name });
 
-         }
 
-         /**
 
-          *  Creates a copy of this plugin.
 
-          */
 
-         clone() {
 
-             return new NetworkPlugin(this.name);
 
-         }
 
-     }
 
-     /**
 
-      *  A **GasCostPlugin** allows a network to provide alternative values when
 
-      *  computing the intrinsic gas required for a transaction.
 
-      */
 
-     class GasCostPlugin extends NetworkPlugin {
 
-         /**
 
-          *  The block number to treat these values as valid from.
 
-          *
 
-          *  This allows a hardfork to have updated values included as well as
 
-          *  mulutiple hardforks to be supported.
 
-          */
 
-         effectiveBlock;
 
-         /**
 
-          *  The transactions base fee.
 
-          */
 
-         txBase;
 
-         /**
 
-          *  The fee for creating a new account.
 
-          */
 
-         txCreate;
 
-         /**
 
-          *  The fee per zero-byte in the data.
 
-          */
 
-         txDataZero;
 
-         /**
 
-          *  The fee per non-zero-byte in the data.
 
-          */
 
-         txDataNonzero;
 
-         /**
 
-          *  The fee per storage key in the [[link-eip-2930]] access list.
 
-          */
 
-         txAccessListStorageKey;
 
-         /**
 
-          *  The fee per address in the [[link-eip-2930]] access list.
 
-          */
 
-         txAccessListAddress;
 
-         /**
 
-          *  Creates a new GasCostPlugin from %%effectiveBlock%% until the
 
-          *  latest block or another GasCostPlugin supercedes that block number,
 
-          *  with the associated %%costs%%.
 
-          */
 
-         constructor(effectiveBlock, costs) {
 
-             if (effectiveBlock == null) {
 
-                 effectiveBlock = 0;
 
-             }
 
-             super(`org.ethers.network.plugins.GasCost#${(effectiveBlock || 0)}`);
 
-             const props = { effectiveBlock };
 
-             function set(name, nullish) {
 
-                 let value = (costs || {})[name];
 
-                 if (value == null) {
 
-                     value = nullish;
 
-                 }
 
-                 assertArgument(typeof (value) === "number", `invalud value for ${name}`, "costs", costs);
 
-                 props[name] = value;
 
-             }
 
-             set("txBase", 21000);
 
-             set("txCreate", 32000);
 
-             set("txDataZero", 4);
 
-             set("txDataNonzero", 16);
 
-             set("txAccessListStorageKey", 1900);
 
-             set("txAccessListAddress", 2400);
 
-             defineProperties(this, props);
 
-         }
 
-         clone() {
 
-             return new GasCostPlugin(this.effectiveBlock, this);
 
-         }
 
-     }
 
-     /**
 
-      *  An **EnsPlugin** allows a [[Network]] to specify the ENS Registry
 
-      *  Contract address and the target network to use when using that
 
-      *  contract.
 
-      *
 
-      *  Various testnets have their own instance of the contract to use, but
 
-      *  in general, the mainnet instance supports multi-chain addresses and
 
-      *  should be used.
 
-      */
 
-     class EnsPlugin extends NetworkPlugin {
 
-         /**
 
-          *  The ENS Registrty Contract address.
 
-          */
 
-         address;
 
-         /**
 
-          *  The chain ID that the ENS contract lives on.
 
-          */
 
-         targetNetwork;
 
-         /**
 
-          *  Creates a new **EnsPlugin** connected to %%address%% on the
 
-          *  %%targetNetwork%%. The default ENS address and mainnet is used
 
-          *  if unspecified.
 
-          */
 
-         constructor(address, targetNetwork) {
 
-             super("org.ethers.plugins.network.Ens");
 
-             defineProperties(this, {
 
-                 address: (address || EnsAddress),
 
-                 targetNetwork: ((targetNetwork == null) ? 1 : targetNetwork)
 
-             });
 
-         }
 
-         clone() {
 
-             return new EnsPlugin(this.address, this.targetNetwork);
 
-         }
 
-     }
 
-     /**
 
-      *  A **FeeDataNetworkPlugin** allows a network to provide and alternate
 
-      *  means to specify its fee data.
 
-      *
 
-      *  For example, a network which does not support [[link-eip-1559]] may
 
-      *  choose to use a Gas Station site to approximate the gas price.
 
-      */
 
-     class FeeDataNetworkPlugin extends NetworkPlugin {
 
-         #feeDataFunc;
 
-         /**
 
-          *  The fee data function provided to the constructor.
 
-          */
 
-         get feeDataFunc() {
 
-             return this.#feeDataFunc;
 
-         }
 
-         /**
 
-          *  Creates a new **FeeDataNetworkPlugin**.
 
-          */
 
-         constructor(feeDataFunc) {
 
-             super("org.ethers.plugins.network.FeeData");
 
-             this.#feeDataFunc = feeDataFunc;
 
-         }
 
-         /**
 
-          *  Resolves to the fee data.
 
-          */
 
-         async getFeeData(provider) {
 
-             return await this.#feeDataFunc(provider);
 
-         }
 
-         clone() {
 
-             return new FeeDataNetworkPlugin(this.#feeDataFunc);
 
-         }
 
-     }
 
-     class FetchUrlFeeDataNetworkPlugin extends NetworkPlugin {
 
-         #url;
 
-         #processFunc;
 
-         /**
 
-          *  The URL to initialize the FetchRequest with in %%processFunc%%.
 
-          */
 
-         get url() { return this.#url; }
 
-         /**
 
-          *  The callback to use when computing the FeeData.
 
-          */
 
-         get processFunc() { return this.#processFunc; }
 
-         /**
 
-          *  Creates a new **FetchUrlFeeDataNetworkPlugin** which will
 
-          *  be used when computing the fee data for the network.
 
-          */
 
-         constructor(url, processFunc) {
 
-             super("org.ethers.plugins.network.FetchUrlFeeDataPlugin");
 
-             this.#url = url;
 
-             this.#processFunc = processFunc;
 
-         }
 
-         // We are immutable, so we can serve as our own clone
 
-         clone() { return this; }
 
-     }
 
-     /*
 
-     export class CustomBlockNetworkPlugin extends NetworkPlugin {
 
-         readonly #blockFunc: (provider: Provider, block: BlockParams<string>) => Block<string>;
 
-         readonly #blockWithTxsFunc: (provider: Provider, block: BlockParams<TransactionResponseParams>) => Block<TransactionResponse>;
 
-         constructor(blockFunc: (provider: Provider, block: BlockParams<string>) => Block<string>, blockWithTxsFunc: (provider: Provider, block: BlockParams<TransactionResponseParams>) => Block<TransactionResponse>) {
 
-             super("org.ethers.network-plugins.custom-block");
 
-             this.#blockFunc = blockFunc;
 
-             this.#blockWithTxsFunc = blockWithTxsFunc;
 
-         }
 
-         async getBlock(provider: Provider, block: BlockParams<string>): Promise<Block<string>> {
 
-             return await this.#blockFunc(provider, block);
 
-         }
 
-         async getBlockions(provider: Provider, block: BlockParams<TransactionResponseParams>): Promise<Block<TransactionResponse>> {
 
-             return await this.#blockWithTxsFunc(provider, block);
 
-         }
 
-         clone(): CustomBlockNetworkPlugin {
 
-             return new CustomBlockNetworkPlugin(this.#blockFunc, this.#blockWithTxsFunc);
 
-         }
 
-     }
 
-     */
 
-     /**
 
-      *  A **Network** encapsulates the various properties required to
 
-      *  interact with a specific chain.
 
-      *
 
-      *  @_subsection: api/providers:Networks  [networks]
 
-      */
 
-     /* * * *
 
-     // Networks which operation against an L2 can use this plugin to
 
-     // specify how to access L1, for the purpose of resolving ENS,
 
-     // for example.
 
-     export class LayerOneConnectionPlugin extends NetworkPlugin {
 
-         readonly provider!: Provider;
 
-     // @TODO: Rename to ChainAccess and allow for connecting to any chain
 
-         constructor(provider: Provider) {
 
-             super("org.ethers.plugins.layer-one-connection");
 
-             defineProperties<LayerOneConnectionPlugin>(this, { provider });
 
-         }
 
-         clone(): LayerOneConnectionPlugin {
 
-             return new LayerOneConnectionPlugin(this.provider);
 
-         }
 
-     }
 
-     */
 
-     const Networks = new Map();
 
-     /**
 
-      *  A **Network** provides access to a chain's properties and allows
 
-      *  for plug-ins to extend functionality.
 
-      */
 
-     class Network {
 
-         #name;
 
-         #chainId;
 
-         #plugins;
 
-         /**
 
-          *  Creates a new **Network** for %%name%% and %%chainId%%.
 
-          */
 
-         constructor(name, chainId) {
 
-             this.#name = name;
 
-             this.#chainId = getBigInt(chainId);
 
-             this.#plugins = new Map();
 
-         }
 
-         /**
 
-          *  Returns a JSON-compatible representation of a Network.
 
-          */
 
-         toJSON() {
 
-             return { name: this.name, chainId: String(this.chainId) };
 
-         }
 
-         /**
 
-          *  The network common name.
 
-          *
 
-          *  This is the canonical name, as networks migh have multiple
 
-          *  names.
 
-          */
 
-         get name() { return this.#name; }
 
-         set name(value) { this.#name = value; }
 
-         /**
 
-          *  The network chain ID.
 
-          */
 
-         get chainId() { return this.#chainId; }
 
-         set chainId(value) { this.#chainId = getBigInt(value, "chainId"); }
 
-         /**
 
-          *  Returns true if %%other%% matches this network. Any chain ID
 
-          *  must match, and if no chain ID is present, the name must match.
 
-          *
 
-          *  This method does not currently check for additional properties,
 
-          *  such as ENS address or plug-in compatibility.
 
-          */
 
-         matches(other) {
 
-             if (other == null) {
 
-                 return false;
 
-             }
 
-             if (typeof (other) === "string") {
 
-                 try {
 
-                     return (this.chainId === getBigInt(other));
 
-                 }
 
-                 catch (error) { }
 
-                 return (this.name === other);
 
-             }
 
-             if (typeof (other) === "number" || typeof (other) === "bigint") {
 
-                 try {
 
-                     return (this.chainId === getBigInt(other));
 
-                 }
 
-                 catch (error) { }
 
-                 return false;
 
-             }
 
-             if (typeof (other) === "object") {
 
-                 if (other.chainId != null) {
 
-                     try {
 
-                         return (this.chainId === getBigInt(other.chainId));
 
-                     }
 
-                     catch (error) { }
 
-                     return false;
 
-                 }
 
-                 if (other.name != null) {
 
-                     return (this.name === other.name);
 
-                 }
 
-                 return false;
 
-             }
 
-             return false;
 
-         }
 
-         /**
 
-          *  Returns the list of plugins currently attached to this Network.
 
-          */
 
-         get plugins() {
 
-             return Array.from(this.#plugins.values());
 
-         }
 
-         /**
 
-          *  Attach a new %%plugin%% to this Network. The network name
 
-          *  must be unique, excluding any fragment.
 
-          */
 
-         attachPlugin(plugin) {
 
-             if (this.#plugins.get(plugin.name)) {
 
-                 throw new Error(`cannot replace existing plugin: ${plugin.name} `);
 
-             }
 
-             this.#plugins.set(plugin.name, plugin.clone());
 
-             return this;
 
-         }
 
-         /**
 
-          *  Return the plugin, if any, matching %%name%% exactly. Plugins
 
-          *  with fragments will not be returned unless %%name%% includes
 
-          *  a fragment.
 
-          */
 
-         getPlugin(name) {
 
-             return (this.#plugins.get(name)) || null;
 
-         }
 
-         /**
 
-          *  Gets a list of all plugins that match %%name%%, with otr without
 
-          *  a fragment.
 
-          */
 
-         getPlugins(basename) {
 
-             return (this.plugins.filter((p) => (p.name.split("#")[0] === basename)));
 
-         }
 
-         /**
 
-          *  Create a copy of this Network.
 
-          */
 
-         clone() {
 
-             const clone = new Network(this.name, this.chainId);
 
-             this.plugins.forEach((plugin) => {
 
-                 clone.attachPlugin(plugin.clone());
 
-             });
 
-             return clone;
 
-         }
 
-         /**
 
-          *  Compute the intrinsic gas required for a transaction.
 
-          *
 
-          *  A GasCostPlugin can be attached to override the default
 
-          *  values.
 
-          */
 
-         computeIntrinsicGas(tx) {
 
-             const costs = this.getPlugin("org.ethers.plugins.network.GasCost") || (new GasCostPlugin());
 
-             let gas = costs.txBase;
 
-             if (tx.to == null) {
 
-                 gas += costs.txCreate;
 
-             }
 
-             if (tx.data) {
 
-                 for (let i = 2; i < tx.data.length; i += 2) {
 
-                     if (tx.data.substring(i, i + 2) === "00") {
 
-                         gas += costs.txDataZero;
 
-                     }
 
-                     else {
 
-                         gas += costs.txDataNonzero;
 
-                     }
 
-                 }
 
-             }
 
-             if (tx.accessList) {
 
-                 const accessList = accessListify(tx.accessList);
 
-                 for (const addr in accessList) {
 
-                     gas += costs.txAccessListAddress + costs.txAccessListStorageKey * accessList[addr].storageKeys.length;
 
-                 }
 
-             }
 
-             return gas;
 
-         }
 
-         /**
 
-          *  Returns a new Network for the %%network%% name or chainId.
 
-          */
 
-         static from(network) {
 
-             injectCommonNetworks();
 
-             // Default network
 
-             if (network == null) {
 
-                 return Network.from("mainnet");
 
-             }
 
-             // Canonical name or chain ID
 
-             if (typeof (network) === "number") {
 
-                 network = BigInt(network);
 
-             }
 
-             if (typeof (network) === "string" || typeof (network) === "bigint") {
 
-                 const networkFunc = Networks.get(network);
 
-                 if (networkFunc) {
 
-                     return networkFunc();
 
-                 }
 
-                 if (typeof (network) === "bigint") {
 
-                     return new Network("unknown", network);
 
-                 }
 
-                 assertArgument(false, "unknown network", "network", network);
 
-             }
 
-             // Clonable with network-like abilities
 
-             if (typeof (network.clone) === "function") {
 
-                 const clone = network.clone();
 
-                 //if (typeof(network.name) !== "string" || typeof(network.chainId) !== "number") {
 
-                 //}
 
-                 return clone;
 
-             }
 
-             // Networkish
 
-             if (typeof (network) === "object") {
 
-                 assertArgument(typeof (network.name) === "string" && typeof (network.chainId) === "number", "invalid network object name or chainId", "network", network);
 
-                 const custom = new Network((network.name), (network.chainId));
 
-                 if (network.ensAddress || network.ensNetwork != null) {
 
-                     custom.attachPlugin(new EnsPlugin(network.ensAddress, network.ensNetwork));
 
-                 }
 
-                 //if ((<any>network).layerOneConnection) {
 
-                 //    custom.attachPlugin(new LayerOneConnectionPlugin((<any>network).layerOneConnection));
 
-                 //}
 
-                 return custom;
 
-             }
 
-             assertArgument(false, "invalid network", "network", network);
 
-         }
 
-         /**
 
-          *  Register %%nameOrChainId%% with a function which returns
 
-          *  an instance of a Network representing that chain.
 
-          */
 
-         static register(nameOrChainId, networkFunc) {
 
-             if (typeof (nameOrChainId) === "number") {
 
-                 nameOrChainId = BigInt(nameOrChainId);
 
-             }
 
-             const existing = Networks.get(nameOrChainId);
 
-             if (existing) {
 
-                 assertArgument(false, `conflicting network for ${JSON.stringify(existing.name)}`, "nameOrChainId", nameOrChainId);
 
-             }
 
-             Networks.set(nameOrChainId, networkFunc);
 
-         }
 
-     }
 
-     // We don't want to bring in formatUnits because it is backed by
 
-     // FixedNumber and we want to keep Networks tiny. The values
 
-     // included by the Gas Stations are also IEEE 754 with lots of
 
-     // rounding issues and exceed the strict checks formatUnits has.
 
-     function parseUnits(_value, decimals) {
 
-         const value = String(_value);
 
-         if (!value.match(/^[0-9.]+$/)) {
 
-             throw new Error(`invalid gwei value: ${_value}`);
 
-         }
 
-         // Break into [ whole, fraction ]
 
-         const comps = value.split(".");
 
-         if (comps.length === 1) {
 
-             comps.push("");
 
-         }
 
-         // More than 1 decimal point or too many fractional positions
 
-         if (comps.length !== 2) {
 
-             throw new Error(`invalid gwei value: ${_value}`);
 
-         }
 
-         // Pad the fraction to 9 decimalplaces
 
-         while (comps[1].length < decimals) {
 
-             comps[1] += "0";
 
-         }
 
-         // Too many decimals and some non-zero ending, take the ceiling
 
-         if (comps[1].length > 9) {
 
-             let frac = BigInt(comps[1].substring(0, 9));
 
-             if (!comps[1].substring(9).match(/^0+$/)) {
 
-                 frac++;
 
-             }
 
-             comps[1] = frac.toString();
 
-         }
 
-         return BigInt(comps[0] + comps[1]);
 
-     }
 
-     // Used by Polygon to use a gas station for fee data
 
-     function getGasStationPlugin(url) {
 
-         return new FetchUrlFeeDataNetworkPlugin(url, async (fetchFeeData, provider, request) => {
 
-             // Prevent Cloudflare from blocking our request in node.js
 
-             request.setHeader("User-Agent", "ethers");
 
-             let response;
 
-             try {
 
-                 const [_response, _feeData] = await Promise.all([
 
-                     request.send(), fetchFeeData()
 
-                 ]);
 
-                 response = _response;
 
-                 const payload = response.bodyJson.standard;
 
-                 const feeData = {
 
-                     gasPrice: _feeData.gasPrice,
 
-                     maxFeePerGas: parseUnits(payload.maxFee, 9),
 
-                     maxPriorityFeePerGas: parseUnits(payload.maxPriorityFee, 9),
 
-                 };
 
-                 return feeData;
 
-             }
 
-             catch (error) {
 
-                 assert(false, `error encountered with polygon gas station (${JSON.stringify(request.url)})`, "SERVER_ERROR", { request, response, error });
 
-             }
 
-         });
 
-     }
 
-     // See: https://chainlist.org
 
-     let injected = false;
 
-     function injectCommonNetworks() {
 
-         if (injected) {
 
-             return;
 
-         }
 
-         injected = true;
 
-         /// Register popular Ethereum networks
 
-         function registerEth(name, chainId, options) {
 
-             const func = function () {
 
-                 const network = new Network(name, chainId);
 
-                 // We use 0 to disable ENS
 
-                 if (options.ensNetwork != null) {
 
-                     network.attachPlugin(new EnsPlugin(null, options.ensNetwork));
 
-                 }
 
-                 network.attachPlugin(new GasCostPlugin());
 
-                 (options.plugins || []).forEach((plugin) => {
 
-                     network.attachPlugin(plugin);
 
-                 });
 
-                 return network;
 
-             };
 
-             // Register the network by name and chain ID
 
-             Network.register(name, func);
 
-             Network.register(chainId, func);
 
-             if (options.altNames) {
 
-                 options.altNames.forEach((name) => {
 
-                     Network.register(name, func);
 
-                 });
 
-             }
 
-         }
 
-         registerEth("mainnet", 1, { ensNetwork: 1, altNames: ["homestead"] });
 
-         registerEth("ropsten", 3, { ensNetwork: 3 });
 
-         registerEth("rinkeby", 4, { ensNetwork: 4 });
 
-         registerEth("goerli", 5, { ensNetwork: 5 });
 
-         registerEth("kovan", 42, { ensNetwork: 42 });
 
-         registerEth("sepolia", 11155111, { ensNetwork: 11155111 });
 
-         registerEth("holesky", 17000, { ensNetwork: 17000 });
 
-         registerEth("classic", 61, {});
 
-         registerEth("classicKotti", 6, {});
 
-         registerEth("arbitrum", 42161, {
 
-             ensNetwork: 1,
 
-         });
 
-         registerEth("arbitrum-goerli", 421613, {});
 
-         registerEth("arbitrum-sepolia", 421614, {});
 
-         registerEth("base", 8453, { ensNetwork: 1 });
 
-         registerEth("base-goerli", 84531, {});
 
-         registerEth("base-sepolia", 84532, {});
 
-         registerEth("bnb", 56, { ensNetwork: 1 });
 
-         registerEth("bnbt", 97, {});
 
-         registerEth("linea", 59144, { ensNetwork: 1 });
 
-         registerEth("linea-goerli", 59140, {});
 
-         registerEth("linea-sepolia", 59141, {});
 
-         registerEth("matic", 137, {
 
-             ensNetwork: 1,
 
-             plugins: [
 
-                 getGasStationPlugin("https:/\/gasstation.polygon.technology/v2")
 
-             ]
 
-         });
 
-         registerEth("matic-amoy", 80002, {});
 
-         registerEth("matic-mumbai", 80001, {
 
-             altNames: ["maticMumbai", "maticmum"],
 
-             plugins: [
 
-                 getGasStationPlugin("https:/\/gasstation-testnet.polygon.technology/v2")
 
-             ]
 
-         });
 
-         registerEth("optimism", 10, {
 
-             ensNetwork: 1,
 
-             plugins: []
 
-         });
 
-         registerEth("optimism-goerli", 420, {});
 
-         registerEth("optimism-sepolia", 11155420, {});
 
-         registerEth("xdai", 100, { ensNetwork: 1 });
 
-     }
 
-     function copy$2(obj) {
 
-         return JSON.parse(JSON.stringify(obj));
 
-     }
 
-     // @TODO: refactor this
 
-     /**
 
-      *  A **PollingBlockSubscriber** polls at a regular interval for a change
 
-      *  in the block number.
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class PollingBlockSubscriber {
 
-         #provider;
 
-         #poller;
 
-         #interval;
 
-         // The most recent block we have scanned for events. The value -2
 
-         // indicates we still need to fetch an initial block number
 
-         #blockNumber;
 
-         /**
 
-          *  Create a new **PollingBlockSubscriber** attached to %%provider%%.
 
-          */
 
-         constructor(provider) {
 
-             this.#provider = provider;
 
-             this.#poller = null;
 
-             this.#interval = 4000;
 
-             this.#blockNumber = -2;
 
-         }
 
-         /**
 
-          *  The polling interval.
 
-          */
 
-         get pollingInterval() { return this.#interval; }
 
-         set pollingInterval(value) { this.#interval = value; }
 
-         async #poll() {
 
-             try {
 
-                 const blockNumber = await this.#provider.getBlockNumber();
 
-                 // Bootstrap poll to setup our initial block number
 
-                 if (this.#blockNumber === -2) {
 
-                     this.#blockNumber = blockNumber;
 
-                     return;
 
-                 }
 
-                 // @TODO: Put a cap on the maximum number of events per loop?
 
-                 if (blockNumber !== this.#blockNumber) {
 
-                     for (let b = this.#blockNumber + 1; b <= blockNumber; b++) {
 
-                         // We have been stopped
 
-                         if (this.#poller == null) {
 
-                             return;
 
-                         }
 
-                         await this.#provider.emit("block", b);
 
-                     }
 
-                     this.#blockNumber = blockNumber;
 
-                 }
 
-             }
 
-             catch (error) {
 
-                 // @TODO: Minor bump, add an "error" event to let subscribers
 
-                 //        know things went awry.
 
-                 //console.log(error);
 
-             }
 
-             // We have been stopped
 
-             if (this.#poller == null) {
 
-                 return;
 
-             }
 
-             this.#poller = this.#provider._setTimeout(this.#poll.bind(this), this.#interval);
 
-         }
 
-         start() {
 
-             if (this.#poller) {
 
-                 return;
 
-             }
 
-             this.#poller = this.#provider._setTimeout(this.#poll.bind(this), this.#interval);
 
-             this.#poll();
 
-         }
 
-         stop() {
 
-             if (!this.#poller) {
 
-                 return;
 
-             }
 
-             this.#provider._clearTimeout(this.#poller);
 
-             this.#poller = null;
 
-         }
 
-         pause(dropWhilePaused) {
 
-             this.stop();
 
-             if (dropWhilePaused) {
 
-                 this.#blockNumber = -2;
 
-             }
 
-         }
 
-         resume() {
 
-             this.start();
 
-         }
 
-     }
 
-     /**
 
-      *  An **OnBlockSubscriber** can be sub-classed, with a [[_poll]]
 
-      *  implmentation which will be called on every new block.
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class OnBlockSubscriber {
 
-         #provider;
 
-         #poll;
 
-         #running;
 
-         /**
 
-          *  Create a new **OnBlockSubscriber** attached to %%provider%%.
 
-          */
 
-         constructor(provider) {
 
-             this.#provider = provider;
 
-             this.#running = false;
 
-             this.#poll = (blockNumber) => {
 
-                 this._poll(blockNumber, this.#provider);
 
-             };
 
-         }
 
-         /**
 
-          *  Called on every new block.
 
-          */
 
-         async _poll(blockNumber, provider) {
 
-             throw new Error("sub-classes must override this");
 
-         }
 
-         start() {
 
-             if (this.#running) {
 
-                 return;
 
-             }
 
-             this.#running = true;
 
-             this.#poll(-2);
 
-             this.#provider.on("block", this.#poll);
 
-         }
 
-         stop() {
 
-             if (!this.#running) {
 
-                 return;
 
-             }
 
-             this.#running = false;
 
-             this.#provider.off("block", this.#poll);
 
-         }
 
-         pause(dropWhilePaused) { this.stop(); }
 
-         resume() { this.start(); }
 
-     }
 
-     class PollingBlockTagSubscriber extends OnBlockSubscriber {
 
-         #tag;
 
-         #lastBlock;
 
-         constructor(provider, tag) {
 
-             super(provider);
 
-             this.#tag = tag;
 
-             this.#lastBlock = -2;
 
-         }
 
-         pause(dropWhilePaused) {
 
-             if (dropWhilePaused) {
 
-                 this.#lastBlock = -2;
 
-             }
 
-             super.pause(dropWhilePaused);
 
-         }
 
-         async _poll(blockNumber, provider) {
 
-             const block = await provider.getBlock(this.#tag);
 
-             if (block == null) {
 
-                 return;
 
-             }
 
-             if (this.#lastBlock === -2) {
 
-                 this.#lastBlock = block.number;
 
-             }
 
-             else if (block.number > this.#lastBlock) {
 
-                 provider.emit(this.#tag, block.number);
 
-                 this.#lastBlock = block.number;
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      *  @_ignore:
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class PollingOrphanSubscriber extends OnBlockSubscriber {
 
-         #filter;
 
-         constructor(provider, filter) {
 
-             super(provider);
 
-             this.#filter = copy$2(filter);
 
-         }
 
-         async _poll(blockNumber, provider) {
 
-             throw new Error("@TODO");
 
-         }
 
-     }
 
-     /**
 
-      *  A **PollingTransactionSubscriber** will poll for a given transaction
 
-      *  hash for its receipt.
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class PollingTransactionSubscriber extends OnBlockSubscriber {
 
-         #hash;
 
-         /**
 
-          *  Create a new **PollingTransactionSubscriber** attached to
 
-          *  %%provider%%, listening for %%hash%%.
 
-          */
 
-         constructor(provider, hash) {
 
-             super(provider);
 
-             this.#hash = hash;
 
-         }
 
-         async _poll(blockNumber, provider) {
 
-             const tx = await provider.getTransactionReceipt(this.#hash);
 
-             if (tx) {
 
-                 provider.emit(this.#hash, tx);
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      *  A **PollingEventSubscriber** will poll for a given filter for its logs.
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class PollingEventSubscriber {
 
-         #provider;
 
-         #filter;
 
-         #poller;
 
-         #running;
 
-         // The most recent block we have scanned for events. The value -2
 
-         // indicates we still need to fetch an initial block number
 
-         #blockNumber;
 
-         /**
 
-          *  Create a new **PollingTransactionSubscriber** attached to
 
-          *  %%provider%%, listening for %%filter%%.
 
-          */
 
-         constructor(provider, filter) {
 
-             this.#provider = provider;
 
-             this.#filter = copy$2(filter);
 
-             this.#poller = this.#poll.bind(this);
 
-             this.#running = false;
 
-             this.#blockNumber = -2;
 
-         }
 
-         async #poll(blockNumber) {
 
-             // The initial block hasn't been determined yet
 
-             if (this.#blockNumber === -2) {
 
-                 return;
 
-             }
 
-             const filter = copy$2(this.#filter);
 
-             filter.fromBlock = this.#blockNumber + 1;
 
-             filter.toBlock = blockNumber;
 
-             const logs = await this.#provider.getLogs(filter);
 
-             // No logs could just mean the node has not indexed them yet,
 
-             // so we keep a sliding window of 60 blocks to keep scanning
 
-             if (logs.length === 0) {
 
-                 if (this.#blockNumber < blockNumber - 60) {
 
-                     this.#blockNumber = blockNumber - 60;
 
-                 }
 
-                 return;
 
-             }
 
-             for (const log of logs) {
 
-                 this.#provider.emit(this.#filter, log);
 
-                 // Only advance the block number when logs were found to
 
-                 // account for networks (like BNB and Polygon) which may
 
-                 // sacrifice event consistency for block event speed
 
-                 this.#blockNumber = log.blockNumber;
 
-             }
 
-         }
 
-         start() {
 
-             if (this.#running) {
 
-                 return;
 
-             }
 
-             this.#running = true;
 
-             if (this.#blockNumber === -2) {
 
-                 this.#provider.getBlockNumber().then((blockNumber) => {
 
-                     this.#blockNumber = blockNumber;
 
-                 });
 
-             }
 
-             this.#provider.on("block", this.#poller);
 
-         }
 
-         stop() {
 
-             if (!this.#running) {
 
-                 return;
 
-             }
 
-             this.#running = false;
 
-             this.#provider.off("block", this.#poller);
 
-         }
 
-         pause(dropWhilePaused) {
 
-             this.stop();
 
-             if (dropWhilePaused) {
 
-                 this.#blockNumber = -2;
 
-             }
 
-         }
 
-         resume() {
 
-             this.start();
 
-         }
 
-     }
 
-     /**
 
-      *  The available providers should suffice for most developers purposes,
 
-      *  but the [[AbstractProvider]] class has many features which enable
 
-      *  sub-classing it for specific purposes.
 
-      *
 
-      *  @_section: api/providers/abstract-provider: Subclassing Provider  [abstract-provider]
 
-      */
 
-     // @TODO
 
-     // Event coalescence
 
-     //   When we register an event with an async value (e.g. address is a Signer
 
-     //   or ENS name), we need to add it immeidately for the Event API, but also
 
-     //   need time to resolve the address. Upon resolving the address, we need to
 
-     //   migrate the listener to the static event. We also need to maintain a map
 
-     //   of Signer/ENS name to address so we can sync respond to listenerCount.
 
-     // Constants
 
-     const BN_2$1 = BigInt(2);
 
-     const MAX_CCIP_REDIRECTS = 10;
 
-     function isPromise$1(value) {
 
-         return (value && typeof (value.then) === "function");
 
-     }
 
-     function getTag(prefix, value) {
 
-         return prefix + ":" + JSON.stringify(value, (k, v) => {
 
-             if (v == null) {
 
-                 return "null";
 
-             }
 
-             if (typeof (v) === "bigint") {
 
-                 return `bigint:${v.toString()}`;
 
-             }
 
-             if (typeof (v) === "string") {
 
-                 return v.toLowerCase();
 
-             }
 
-             // Sort object keys
 
-             if (typeof (v) === "object" && !Array.isArray(v)) {
 
-                 const keys = Object.keys(v);
 
-                 keys.sort();
 
-                 return keys.reduce((accum, key) => {
 
-                     accum[key] = v[key];
 
-                     return accum;
 
-                 }, {});
 
-             }
 
-             return v;
 
-         });
 
-     }
 
-     /**
 
-      *  An **UnmanagedSubscriber** is useful for events which do not require
 
-      *  any additional management, such as ``"debug"`` which only requires
 
-      *  emit in synchronous event loop triggered calls.
 
-      */
 
-     class UnmanagedSubscriber {
 
-         /**
 
-          *  The name fof the event.
 
-          */
 
-         name;
 
-         /**
 
-          *  Create a new UnmanagedSubscriber with %%name%%.
 
-          */
 
-         constructor(name) { defineProperties(this, { name }); }
 
-         start() { }
 
-         stop() { }
 
-         pause(dropWhilePaused) { }
 
-         resume() { }
 
-     }
 
-     function copy$1(value) {
 
-         return JSON.parse(JSON.stringify(value));
 
-     }
 
-     function concisify(items) {
 
-         items = Array.from((new Set(items)).values());
 
-         items.sort();
 
-         return items;
 
-     }
 
-     async function getSubscription(_event, provider) {
 
-         if (_event == null) {
 
-             throw new Error("invalid event");
 
-         }
 
-         // Normalize topic array info an EventFilter
 
-         if (Array.isArray(_event)) {
 
-             _event = { topics: _event };
 
-         }
 
-         if (typeof (_event) === "string") {
 
-             switch (_event) {
 
-                 case "block":
 
-                 case "debug":
 
-                 case "error":
 
-                 case "finalized":
 
-                 case "network":
 
-                 case "pending":
 
-                 case "safe": {
 
-                     return { type: _event, tag: _event };
 
-                 }
 
-             }
 
-         }
 
-         if (isHexString(_event, 32)) {
 
-             const hash = _event.toLowerCase();
 
-             return { type: "transaction", tag: getTag("tx", { hash }), hash };
 
-         }
 
-         if (_event.orphan) {
 
-             const event = _event;
 
-             // @TODO: Should lowercase and whatnot things here instead of copy...
 
-             return { type: "orphan", tag: getTag("orphan", event), filter: copy$1(event) };
 
-         }
 
-         if ((_event.address || _event.topics)) {
 
-             const event = _event;
 
-             const filter = {
 
-                 topics: ((event.topics || []).map((t) => {
 
-                     if (t == null) {
 
-                         return null;
 
-                     }
 
-                     if (Array.isArray(t)) {
 
-                         return concisify(t.map((t) => t.toLowerCase()));
 
-                     }
 
-                     return t.toLowerCase();
 
-                 }))
 
-             };
 
-             if (event.address) {
 
-                 const addresses = [];
 
-                 const promises = [];
 
-                 const addAddress = (addr) => {
 
-                     if (isHexString(addr)) {
 
-                         addresses.push(addr);
 
-                     }
 
-                     else {
 
-                         promises.push((async () => {
 
-                             addresses.push(await resolveAddress(addr, provider));
 
-                         })());
 
-                     }
 
-                 };
 
-                 if (Array.isArray(event.address)) {
 
-                     event.address.forEach(addAddress);
 
-                 }
 
-                 else {
 
-                     addAddress(event.address);
 
-                 }
 
-                 if (promises.length) {
 
-                     await Promise.all(promises);
 
-                 }
 
-                 filter.address = concisify(addresses.map((a) => a.toLowerCase()));
 
-             }
 
-             return { filter, tag: getTag("event", filter), type: "event" };
 
-         }
 
-         assertArgument(false, "unknown ProviderEvent", "event", _event);
 
-     }
 
-     function getTime$1() { return (new Date()).getTime(); }
 
-     const defaultOptions$1 = {
 
-         cacheTimeout: 250,
 
-         pollingInterval: 4000
 
-     };
 
-     /**
 
-      *  An **AbstractProvider** provides a base class for other sub-classes to
 
-      *  implement the [[Provider]] API by normalizing input arguments and
 
-      *  formatting output results as well as tracking events for consistent
 
-      *  behaviour on an eventually-consistent network.
 
-      */
 
-     class AbstractProvider {
 
-         #subs;
 
-         #plugins;
 
-         // null=unpaused, true=paused+dropWhilePaused, false=paused
 
-         #pausedState;
 
-         #destroyed;
 
-         #networkPromise;
 
-         #anyNetwork;
 
-         #performCache;
 
-         // The most recent block number if running an event or -1 if no "block" event
 
-         #lastBlockNumber;
 
-         #nextTimer;
 
-         #timers;
 
-         #disableCcipRead;
 
-         #options;
 
-         /**
 
-          *  Create a new **AbstractProvider** connected to %%network%%, or
 
-          *  use the various network detection capabilities to discover the
 
-          *  [[Network]] if necessary.
 
-          */
 
-         constructor(_network, options) {
 
-             this.#options = Object.assign({}, defaultOptions$1, options || {});
 
-             if (_network === "any") {
 
-                 this.#anyNetwork = true;
 
-                 this.#networkPromise = null;
 
-             }
 
-             else if (_network) {
 
-                 const network = Network.from(_network);
 
-                 this.#anyNetwork = false;
 
-                 this.#networkPromise = Promise.resolve(network);
 
-                 setTimeout(() => { this.emit("network", network, null); }, 0);
 
-             }
 
-             else {
 
-                 this.#anyNetwork = false;
 
-                 this.#networkPromise = null;
 
-             }
 
-             this.#lastBlockNumber = -1;
 
-             this.#performCache = new Map();
 
-             this.#subs = new Map();
 
-             this.#plugins = new Map();
 
-             this.#pausedState = null;
 
-             this.#destroyed = false;
 
-             this.#nextTimer = 1;
 
-             this.#timers = new Map();
 
-             this.#disableCcipRead = false;
 
-         }
 
-         get pollingInterval() { return this.#options.pollingInterval; }
 
-         /**
 
-          *  Returns ``this``, to allow an **AbstractProvider** to implement
 
-          *  the [[ContractRunner]] interface.
 
-          */
 
-         get provider() { return this; }
 
-         /**
 
-          *  Returns all the registered plug-ins.
 
-          */
 
-         get plugins() {
 
-             return Array.from(this.#plugins.values());
 
-         }
 
-         /**
 
-          *  Attach a new plug-in.
 
-          */
 
-         attachPlugin(plugin) {
 
-             if (this.#plugins.get(plugin.name)) {
 
-                 throw new Error(`cannot replace existing plugin: ${plugin.name} `);
 
-             }
 
-             this.#plugins.set(plugin.name, plugin.connect(this));
 
-             return this;
 
-         }
 
-         /**
 
-          *  Get a plugin by name.
 
-          */
 
-         getPlugin(name) {
 
-             return (this.#plugins.get(name)) || null;
 
-         }
 
-         /**
 
-          *  Prevent any CCIP-read operation, regardless of whether requested
 
-          *  in a [[call]] using ``enableCcipRead``.
 
-          */
 
-         get disableCcipRead() { return this.#disableCcipRead; }
 
-         set disableCcipRead(value) { this.#disableCcipRead = !!value; }
 
-         // Shares multiple identical requests made during the same 250ms
 
-         async #perform(req) {
 
-             const timeout = this.#options.cacheTimeout;
 
-             // Caching disabled
 
-             if (timeout < 0) {
 
-                 return await this._perform(req);
 
-             }
 
-             // Create a tag
 
-             const tag = getTag(req.method, req);
 
-             let perform = this.#performCache.get(tag);
 
-             if (!perform) {
 
-                 perform = this._perform(req);
 
-                 this.#performCache.set(tag, perform);
 
-                 setTimeout(() => {
 
-                     if (this.#performCache.get(tag) === perform) {
 
-                         this.#performCache.delete(tag);
 
-                     }
 
-                 }, timeout);
 
-             }
 
-             return await perform;
 
-         }
 
-         /**
 
-          *  Resolves to the data for executing the CCIP-read operations.
 
-          */
 
-         async ccipReadFetch(tx, calldata, urls) {
 
-             if (this.disableCcipRead || urls.length === 0 || tx.to == null) {
 
-                 return null;
 
-             }
 
-             const sender = tx.to.toLowerCase();
 
-             const data = calldata.toLowerCase();
 
-             const errorMessages = [];
 
-             for (let i = 0; i < urls.length; i++) {
 
-                 const url = urls[i];
 
-                 // URL expansion
 
-                 const href = url.replace("{sender}", sender).replace("{data}", data);
 
-                 // If no {data} is present, use POST; otherwise GET
 
-                 //const json: string | null = (url.indexOf("{data}") >= 0) ? null: JSON.stringify({ data, sender });
 
-                 //const result = await fetchJson({ url: href, errorPassThrough: true }, json, (value, response) => {
 
-                 //    value.status = response.statusCode;
 
-                 //    return value;
 
-                 //});
 
-                 const request = new FetchRequest(href);
 
-                 if (url.indexOf("{data}") === -1) {
 
-                     request.body = { data, sender };
 
-                 }
 
-                 this.emit("debug", { action: "sendCcipReadFetchRequest", request, index: i, urls });
 
-                 let errorMessage = "unknown error";
 
-                 // Fetch the resource...
 
-                 let resp;
 
-                 try {
 
-                     resp = await request.send();
 
-                 }
 
-                 catch (error) {
 
-                     // ...low-level fetch error (missing host, bad SSL, etc.),
 
-                     // so try next URL
 
-                     errorMessages.push(error.message);
 
-                     this.emit("debug", { action: "receiveCcipReadFetchError", request, result: { error } });
 
-                     continue;
 
-                 }
 
-                 try {
 
-                     const result = resp.bodyJson;
 
-                     if (result.data) {
 
-                         this.emit("debug", { action: "receiveCcipReadFetchResult", request, result });
 
-                         return result.data;
 
-                     }
 
-                     if (result.message) {
 
-                         errorMessage = result.message;
 
-                     }
 
-                     this.emit("debug", { action: "receiveCcipReadFetchError", request, result });
 
-                 }
 
-                 catch (error) { }
 
-                 // 4xx indicates the result is not present; stop
 
-                 assert(resp.statusCode < 400 || resp.statusCode >= 500, `response not found during CCIP fetch: ${errorMessage}`, "OFFCHAIN_FAULT", { reason: "404_MISSING_RESOURCE", transaction: tx, info: { url, errorMessage } });
 
-                 // 5xx indicates server issue; try the next url
 
-                 errorMessages.push(errorMessage);
 
-             }
 
-             assert(false, `error encountered during CCIP fetch: ${errorMessages.map((m) => JSON.stringify(m)).join(", ")}`, "OFFCHAIN_FAULT", {
 
-                 reason: "500_SERVER_ERROR",
 
-                 transaction: tx, info: { urls, errorMessages }
 
-             });
 
-         }
 
-         /**
 
-          *  Provides the opportunity for a sub-class to wrap a block before
 
-          *  returning it, to add additional properties or an alternate
 
-          *  sub-class of [[Block]].
 
-          */
 
-         _wrapBlock(value, network) {
 
-             return new Block(formatBlock(value), this);
 
-         }
 
-         /**
 
-          *  Provides the opportunity for a sub-class to wrap a log before
 
-          *  returning it, to add additional properties or an alternate
 
-          *  sub-class of [[Log]].
 
-          */
 
-         _wrapLog(value, network) {
 
-             return new Log(formatLog(value), this);
 
-         }
 
-         /**
 
-          *  Provides the opportunity for a sub-class to wrap a transaction
 
-          *  receipt before returning it, to add additional properties or an
 
-          *  alternate sub-class of [[TransactionReceipt]].
 
-          */
 
-         _wrapTransactionReceipt(value, network) {
 
-             return new TransactionReceipt(formatTransactionReceipt(value), this);
 
-         }
 
-         /**
 
-          *  Provides the opportunity for a sub-class to wrap a transaction
 
-          *  response before returning it, to add additional properties or an
 
-          *  alternate sub-class of [[TransactionResponse]].
 
-          */
 
-         _wrapTransactionResponse(tx, network) {
 
-             return new TransactionResponse(formatTransactionResponse(tx), this);
 
-         }
 
-         /**
 
-          *  Resolves to the Network, forcing a network detection using whatever
 
-          *  technique the sub-class requires.
 
-          *
 
-          *  Sub-classes **must** override this.
 
-          */
 
-         _detectNetwork() {
 
-             assert(false, "sub-classes must implement this", "UNSUPPORTED_OPERATION", {
 
-                 operation: "_detectNetwork"
 
-             });
 
-         }
 
-         /**
 
-          *  Sub-classes should use this to perform all built-in operations. All
 
-          *  methods sanitizes and normalizes the values passed into this.
 
-          *
 
-          *  Sub-classes **must** override this.
 
-          */
 
-         async _perform(req) {
 
-             assert(false, `unsupported method: ${req.method}`, "UNSUPPORTED_OPERATION", {
 
-                 operation: req.method,
 
-                 info: req
 
-             });
 
-         }
 
-         // State
 
-         async getBlockNumber() {
 
-             const blockNumber = getNumber(await this.#perform({ method: "getBlockNumber" }), "%response");
 
-             if (this.#lastBlockNumber >= 0) {
 
-                 this.#lastBlockNumber = blockNumber;
 
-             }
 
-             return blockNumber;
 
-         }
 
-         /**
 
-          *  Returns or resolves to the address for %%address%%, resolving ENS
 
-          *  names and [[Addressable]] objects and returning if already an
 
-          *  address.
 
-          */
 
-         _getAddress(address) {
 
-             return resolveAddress(address, this);
 
-         }
 
-         /**
 
-          *  Returns or resolves to a valid block tag for %%blockTag%%, resolving
 
-          *  negative values and returning if already a valid block tag.
 
-          */
 
-         _getBlockTag(blockTag) {
 
-             if (blockTag == null) {
 
-                 return "latest";
 
-             }
 
-             switch (blockTag) {
 
-                 case "earliest":
 
-                     return "0x0";
 
-                 case "finalized":
 
-                 case "latest":
 
-                 case "pending":
 
-                 case "safe":
 
-                     return blockTag;
 
-             }
 
-             if (isHexString(blockTag)) {
 
-                 if (isHexString(blockTag, 32)) {
 
-                     return blockTag;
 
-                 }
 
-                 return toQuantity(blockTag);
 
-             }
 
-             if (typeof (blockTag) === "bigint") {
 
-                 blockTag = getNumber(blockTag, "blockTag");
 
-             }
 
-             if (typeof (blockTag) === "number") {
 
-                 if (blockTag >= 0) {
 
-                     return toQuantity(blockTag);
 
-                 }
 
-                 if (this.#lastBlockNumber >= 0) {
 
-                     return toQuantity(this.#lastBlockNumber + blockTag);
 
-                 }
 
-                 return this.getBlockNumber().then((b) => toQuantity(b + blockTag));
 
-             }
 
-             assertArgument(false, "invalid blockTag", "blockTag", blockTag);
 
-         }
 
-         /**
 
-          *  Returns or resolves to a filter for %%filter%%, resolving any ENS
 
-          *  names or [[Addressable]] object and returning if already a valid
 
-          *  filter.
 
-          */
 
-         _getFilter(filter) {
 
-             // Create a canonical representation of the topics
 
-             const topics = (filter.topics || []).map((t) => {
 
-                 if (t == null) {
 
-                     return null;
 
-                 }
 
-                 if (Array.isArray(t)) {
 
-                     return concisify(t.map((t) => t.toLowerCase()));
 
-                 }
 
-                 return t.toLowerCase();
 
-             });
 
-             const blockHash = ("blockHash" in filter) ? filter.blockHash : undefined;
 
-             const resolve = (_address, fromBlock, toBlock) => {
 
-                 let address = undefined;
 
-                 switch (_address.length) {
 
-                     case 0: break;
 
-                     case 1:
 
-                         address = _address[0];
 
-                         break;
 
-                     default:
 
-                         _address.sort();
 
-                         address = _address;
 
-                 }
 
-                 if (blockHash) {
 
-                     if (fromBlock != null || toBlock != null) {
 
-                         throw new Error("invalid filter");
 
-                     }
 
-                 }
 
-                 const filter = {};
 
-                 if (address) {
 
-                     filter.address = address;
 
-                 }
 
-                 if (topics.length) {
 
-                     filter.topics = topics;
 
-                 }
 
-                 if (fromBlock) {
 
-                     filter.fromBlock = fromBlock;
 
-                 }
 
-                 if (toBlock) {
 
-                     filter.toBlock = toBlock;
 
-                 }
 
-                 if (blockHash) {
 
-                     filter.blockHash = blockHash;
 
-                 }
 
-                 return filter;
 
-             };
 
-             // Addresses could be async (ENS names or Addressables)
 
-             let address = [];
 
-             if (filter.address) {
 
-                 if (Array.isArray(filter.address)) {
 
-                     for (const addr of filter.address) {
 
-                         address.push(this._getAddress(addr));
 
-                     }
 
-                 }
 
-                 else {
 
-                     address.push(this._getAddress(filter.address));
 
-                 }
 
-             }
 
-             let fromBlock = undefined;
 
-             if ("fromBlock" in filter) {
 
-                 fromBlock = this._getBlockTag(filter.fromBlock);
 
-             }
 
-             let toBlock = undefined;
 
-             if ("toBlock" in filter) {
 
-                 toBlock = this._getBlockTag(filter.toBlock);
 
-             }
 
-             if (address.filter((a) => (typeof (a) !== "string")).length ||
 
-                 (fromBlock != null && typeof (fromBlock) !== "string") ||
 
-                 (toBlock != null && typeof (toBlock) !== "string")) {
 
-                 return Promise.all([Promise.all(address), fromBlock, toBlock]).then((result) => {
 
-                     return resolve(result[0], result[1], result[2]);
 
-                 });
 
-             }
 
-             return resolve(address, fromBlock, toBlock);
 
-         }
 
-         /**
 
-          *  Returns or resolves to a transaction for %%request%%, resolving
 
-          *  any ENS names or [[Addressable]] and returning if already a valid
 
-          *  transaction.
 
-          */
 
-         _getTransactionRequest(_request) {
 
-             const request = copyRequest(_request);
 
-             const promises = [];
 
-             ["to", "from"].forEach((key) => {
 
-                 if (request[key] == null) {
 
-                     return;
 
-                 }
 
-                 const addr = resolveAddress(request[key], this);
 
-                 if (isPromise$1(addr)) {
 
-                     promises.push((async function () { request[key] = await addr; })());
 
-                 }
 
-                 else {
 
-                     request[key] = addr;
 
-                 }
 
-             });
 
-             if (request.blockTag != null) {
 
-                 const blockTag = this._getBlockTag(request.blockTag);
 
-                 if (isPromise$1(blockTag)) {
 
-                     promises.push((async function () { request.blockTag = await blockTag; })());
 
-                 }
 
-                 else {
 
-                     request.blockTag = blockTag;
 
-                 }
 
-             }
 
-             if (promises.length) {
 
-                 return (async function () {
 
-                     await Promise.all(promises);
 
-                     return request;
 
-                 })();
 
-             }
 
-             return request;
 
-         }
 
-         async getNetwork() {
 
-             // No explicit network was set and this is our first time
 
-             if (this.#networkPromise == null) {
 
-                 // Detect the current network (shared with all calls)
 
-                 const detectNetwork = (async () => {
 
-                     try {
 
-                         const network = await this._detectNetwork();
 
-                         this.emit("network", network, null);
 
-                         return network;
 
-                     }
 
-                     catch (error) {
 
-                         if (this.#networkPromise === detectNetwork) {
 
-                             this.#networkPromise = null;
 
-                         }
 
-                         throw error;
 
-                     }
 
-                 })();
 
-                 this.#networkPromise = detectNetwork;
 
-                 return (await detectNetwork).clone();
 
-             }
 
-             const networkPromise = this.#networkPromise;
 
-             const [expected, actual] = await Promise.all([
 
-                 networkPromise,
 
-                 this._detectNetwork() // The actual connected network
 
-             ]);
 
-             if (expected.chainId !== actual.chainId) {
 
-                 if (this.#anyNetwork) {
 
-                     // The "any" network can change, so notify listeners
 
-                     this.emit("network", actual, expected);
 
-                     // Update the network if something else hasn't already changed it
 
-                     if (this.#networkPromise === networkPromise) {
 
-                         this.#networkPromise = Promise.resolve(actual);
 
-                     }
 
-                 }
 
-                 else {
 
-                     // Otherwise, we do not allow changes to the underlying network
 
-                     assert(false, `network changed: ${expected.chainId} => ${actual.chainId} `, "NETWORK_ERROR", {
 
-                         event: "changed"
 
-                     });
 
-                 }
 
-             }
 
-             return expected.clone();
 
-         }
 
-         async getFeeData() {
 
-             const network = await this.getNetwork();
 
-             const getFeeDataFunc = async () => {
 
-                 const { _block, gasPrice, priorityFee } = await resolveProperties({
 
-                     _block: this.#getBlock("latest", false),
 
-                     gasPrice: ((async () => {
 
-                         try {
 
-                             const value = await this.#perform({ method: "getGasPrice" });
 
-                             return getBigInt(value, "%response");
 
-                         }
 
-                         catch (error) { }
 
-                         return null;
 
-                     })()),
 
-                     priorityFee: ((async () => {
 
-                         try {
 
-                             const value = await this.#perform({ method: "getPriorityFee" });
 
-                             return getBigInt(value, "%response");
 
-                         }
 
-                         catch (error) { }
 
-                         return null;
 
-                     })())
 
-                 });
 
-                 let maxFeePerGas = null;
 
-                 let maxPriorityFeePerGas = null;
 
-                 // These are the recommended EIP-1559 heuristics for fee data
 
-                 const block = this._wrapBlock(_block, network);
 
-                 if (block && block.baseFeePerGas) {
 
-                     maxPriorityFeePerGas = (priorityFee != null) ? priorityFee : BigInt("1000000000");
 
-                     maxFeePerGas = (block.baseFeePerGas * BN_2$1) + maxPriorityFeePerGas;
 
-                 }
 
-                 return new FeeData(gasPrice, maxFeePerGas, maxPriorityFeePerGas);
 
-             };
 
-             // Check for a FeeDataNetWorkPlugin
 
-             const plugin = network.getPlugin("org.ethers.plugins.network.FetchUrlFeeDataPlugin");
 
-             if (plugin) {
 
-                 const req = new FetchRequest(plugin.url);
 
-                 const feeData = await plugin.processFunc(getFeeDataFunc, this, req);
 
-                 return new FeeData(feeData.gasPrice, feeData.maxFeePerGas, feeData.maxPriorityFeePerGas);
 
-             }
 
-             return await getFeeDataFunc();
 
-         }
 
-         async estimateGas(_tx) {
 
-             let tx = this._getTransactionRequest(_tx);
 
-             if (isPromise$1(tx)) {
 
-                 tx = await tx;
 
-             }
 
-             return getBigInt(await this.#perform({
 
-                 method: "estimateGas", transaction: tx
 
-             }), "%response");
 
-         }
 
-         async #call(tx, blockTag, attempt) {
 
-             assert(attempt < MAX_CCIP_REDIRECTS, "CCIP read exceeded maximum redirections", "OFFCHAIN_FAULT", {
 
-                 reason: "TOO_MANY_REDIRECTS",
 
-                 transaction: Object.assign({}, tx, { blockTag, enableCcipRead: true })
 
-             });
 
-             // This came in as a PerformActionTransaction, so to/from are safe; we can cast
 
-             const transaction = copyRequest(tx);
 
-             try {
 
-                 return hexlify(await this._perform({ method: "call", transaction, blockTag }));
 
-             }
 
-             catch (error) {
 
-                 // CCIP Read OffchainLookup
 
-                 if (!this.disableCcipRead && isCallException(error) && error.data && attempt >= 0 && blockTag === "latest" && transaction.to != null && dataSlice(error.data, 0, 4) === "0x556f1830") {
 
-                     const data = error.data;
 
-                     const txSender = await resolveAddress(transaction.to, this);
 
-                     // Parse the CCIP Read Arguments
 
-                     let ccipArgs;
 
-                     try {
 
-                         ccipArgs = parseOffchainLookup(dataSlice(error.data, 4));
 
-                     }
 
-                     catch (error) {
 
-                         assert(false, error.message, "OFFCHAIN_FAULT", {
 
-                             reason: "BAD_DATA", transaction, info: { data }
 
-                         });
 
-                     }
 
-                     // Check the sender of the OffchainLookup matches the transaction
 
-                     assert(ccipArgs.sender.toLowerCase() === txSender.toLowerCase(), "CCIP Read sender mismatch", "CALL_EXCEPTION", {
 
-                         action: "call",
 
-                         data,
 
-                         reason: "OffchainLookup",
 
-                         transaction: transaction,
 
-                         invocation: null,
 
-                         revert: {
 
-                             signature: "OffchainLookup(address,string[],bytes,bytes4,bytes)",
 
-                             name: "OffchainLookup",
 
-                             args: ccipArgs.errorArgs
 
-                         }
 
-                     });
 
-                     const ccipResult = await this.ccipReadFetch(transaction, ccipArgs.calldata, ccipArgs.urls);
 
-                     assert(ccipResult != null, "CCIP Read failed to fetch data", "OFFCHAIN_FAULT", {
 
-                         reason: "FETCH_FAILED", transaction, info: { data: error.data, errorArgs: ccipArgs.errorArgs }
 
-                     });
 
-                     const tx = {
 
-                         to: txSender,
 
-                         data: concat([ccipArgs.selector, encodeBytes([ccipResult, ccipArgs.extraData])])
 
-                     };
 
-                     this.emit("debug", { action: "sendCcipReadCall", transaction: tx });
 
-                     try {
 
-                         const result = await this.#call(tx, blockTag, attempt + 1);
 
-                         this.emit("debug", { action: "receiveCcipReadCallResult", transaction: Object.assign({}, tx), result });
 
-                         return result;
 
-                     }
 
-                     catch (error) {
 
-                         this.emit("debug", { action: "receiveCcipReadCallError", transaction: Object.assign({}, tx), error });
 
-                         throw error;
 
-                     }
 
-                 }
 
-                 throw error;
 
-             }
 
-         }
 
-         async #checkNetwork(promise) {
 
-             const { value } = await resolveProperties({
 
-                 network: this.getNetwork(),
 
-                 value: promise
 
-             });
 
-             return value;
 
-         }
 
-         async call(_tx) {
 
-             const { tx, blockTag } = await resolveProperties({
 
-                 tx: this._getTransactionRequest(_tx),
 
-                 blockTag: this._getBlockTag(_tx.blockTag)
 
-             });
 
-             return await this.#checkNetwork(this.#call(tx, blockTag, _tx.enableCcipRead ? 0 : -1));
 
-         }
 
-         // Account
 
-         async #getAccountValue(request, _address, _blockTag) {
 
-             let address = this._getAddress(_address);
 
-             let blockTag = this._getBlockTag(_blockTag);
 
-             if (typeof (address) !== "string" || typeof (blockTag) !== "string") {
 
-                 [address, blockTag] = await Promise.all([address, blockTag]);
 
-             }
 
-             return await this.#checkNetwork(this.#perform(Object.assign(request, { address, blockTag })));
 
-         }
 
-         async getBalance(address, blockTag) {
 
-             return getBigInt(await this.#getAccountValue({ method: "getBalance" }, address, blockTag), "%response");
 
-         }
 
-         async getTransactionCount(address, blockTag) {
 
-             return getNumber(await this.#getAccountValue({ method: "getTransactionCount" }, address, blockTag), "%response");
 
-         }
 
-         async getCode(address, blockTag) {
 
-             return hexlify(await this.#getAccountValue({ method: "getCode" }, address, blockTag));
 
-         }
 
-         async getStorage(address, _position, blockTag) {
 
-             const position = getBigInt(_position, "position");
 
-             return hexlify(await this.#getAccountValue({ method: "getStorage", position }, address, blockTag));
 
-         }
 
-         // Write
 
-         async broadcastTransaction(signedTx) {
 
-             const { blockNumber, hash, network } = await resolveProperties({
 
-                 blockNumber: this.getBlockNumber(),
 
-                 hash: this._perform({
 
-                     method: "broadcastTransaction",
 
-                     signedTransaction: signedTx
 
-                 }),
 
-                 network: this.getNetwork()
 
-             });
 
-             const tx = Transaction.from(signedTx);
 
-             if (tx.hash !== hash) {
 
-                 throw new Error("@TODO: the returned hash did not match");
 
-             }
 
-             return this._wrapTransactionResponse(tx, network).replaceableTransaction(blockNumber);
 
-         }
 
-         async #getBlock(block, includeTransactions) {
 
-             // @TODO: Add CustomBlockPlugin check
 
-             if (isHexString(block, 32)) {
 
-                 return await this.#perform({
 
-                     method: "getBlock", blockHash: block, includeTransactions
 
-                 });
 
-             }
 
-             let blockTag = this._getBlockTag(block);
 
-             if (typeof (blockTag) !== "string") {
 
-                 blockTag = await blockTag;
 
-             }
 
-             return await this.#perform({
 
-                 method: "getBlock", blockTag, includeTransactions
 
-             });
 
-         }
 
-         // Queries
 
-         async getBlock(block, prefetchTxs) {
 
-             const { network, params } = await resolveProperties({
 
-                 network: this.getNetwork(),
 
-                 params: this.#getBlock(block, !!prefetchTxs)
 
-             });
 
-             if (params == null) {
 
-                 return null;
 
-             }
 
-             return this._wrapBlock(params, network);
 
-         }
 
-         async getTransaction(hash) {
 
-             const { network, params } = await resolveProperties({
 
-                 network: this.getNetwork(),
 
-                 params: this.#perform({ method: "getTransaction", hash })
 
-             });
 
-             if (params == null) {
 
-                 return null;
 
-             }
 
-             return this._wrapTransactionResponse(params, network);
 
-         }
 
-         async getTransactionReceipt(hash) {
 
-             const { network, params } = await resolveProperties({
 
-                 network: this.getNetwork(),
 
-                 params: this.#perform({ method: "getTransactionReceipt", hash })
 
-             });
 
-             if (params == null) {
 
-                 return null;
 
-             }
 
-             // Some backends did not backfill the effectiveGasPrice into old transactions
 
-             // in the receipt, so we look it up manually and inject it.
 
-             if (params.gasPrice == null && params.effectiveGasPrice == null) {
 
-                 const tx = await this.#perform({ method: "getTransaction", hash });
 
-                 if (tx == null) {
 
-                     throw new Error("report this; could not find tx or effectiveGasPrice");
 
-                 }
 
-                 params.effectiveGasPrice = tx.gasPrice;
 
-             }
 
-             return this._wrapTransactionReceipt(params, network);
 
-         }
 
-         async getTransactionResult(hash) {
 
-             const { result } = await resolveProperties({
 
-                 network: this.getNetwork(),
 
-                 result: this.#perform({ method: "getTransactionResult", hash })
 
-             });
 
-             if (result == null) {
 
-                 return null;
 
-             }
 
-             return hexlify(result);
 
-         }
 
-         // Bloom-filter Queries
 
-         async getLogs(_filter) {
 
-             let filter = this._getFilter(_filter);
 
-             if (isPromise$1(filter)) {
 
-                 filter = await filter;
 
-             }
 
-             const { network, params } = await resolveProperties({
 
-                 network: this.getNetwork(),
 
-                 params: this.#perform({ method: "getLogs", filter })
 
-             });
 
-             return params.map((p) => this._wrapLog(p, network));
 
-         }
 
-         // ENS
 
-         _getProvider(chainId) {
 
-             assert(false, "provider cannot connect to target network", "UNSUPPORTED_OPERATION", {
 
-                 operation: "_getProvider()"
 
-             });
 
-         }
 
-         async getResolver(name) {
 
-             return await EnsResolver.fromName(this, name);
 
-         }
 
-         async getAvatar(name) {
 
-             const resolver = await this.getResolver(name);
 
-             if (resolver) {
 
-                 return await resolver.getAvatar();
 
-             }
 
-             return null;
 
-         }
 
-         async resolveName(name) {
 
-             const resolver = await this.getResolver(name);
 
-             if (resolver) {
 
-                 return await resolver.getAddress();
 
-             }
 
-             return null;
 
-         }
 
-         async lookupAddress(address) {
 
-             address = getAddress(address);
 
-             const node = namehash(address.substring(2).toLowerCase() + ".addr.reverse");
 
-             try {
 
-                 const ensAddr = await EnsResolver.getEnsAddress(this);
 
-                 const ensContract = new Contract(ensAddr, [
 
-                     "function resolver(bytes32) view returns (address)"
 
-                 ], this);
 
-                 const resolver = await ensContract.resolver(node);
 
-                 if (resolver == null || resolver === ZeroAddress) {
 
-                     return null;
 
-                 }
 
-                 const resolverContract = new Contract(resolver, [
 
-                     "function name(bytes32) view returns (string)"
 
-                 ], this);
 
-                 const name = await resolverContract.name(node);
 
-                 // Failed forward resolution
 
-                 const check = await this.resolveName(name);
 
-                 if (check !== address) {
 
-                     return null;
 
-                 }
 
-                 return name;
 
-             }
 
-             catch (error) {
 
-                 // No data was returned from the resolver
 
-                 if (isError(error, "BAD_DATA") && error.value === "0x") {
 
-                     return null;
 
-                 }
 
-                 // Something reerted
 
-                 if (isError(error, "CALL_EXCEPTION")) {
 
-                     return null;
 
-                 }
 
-                 throw error;
 
-             }
 
-             return null;
 
-         }
 
-         async waitForTransaction(hash, _confirms, timeout) {
 
-             const confirms = (_confirms != null) ? _confirms : 1;
 
-             if (confirms === 0) {
 
-                 return this.getTransactionReceipt(hash);
 
-             }
 
-             return new Promise(async (resolve, reject) => {
 
-                 let timer = null;
 
-                 const listener = (async (blockNumber) => {
 
-                     try {
 
-                         const receipt = await this.getTransactionReceipt(hash);
 
-                         if (receipt != null) {
 
-                             if (blockNumber - receipt.blockNumber + 1 >= confirms) {
 
-                                 resolve(receipt);
 
-                                 //this.off("block", listener);
 
-                                 if (timer) {
 
-                                     clearTimeout(timer);
 
-                                     timer = null;
 
-                                 }
 
-                                 return;
 
-                             }
 
-                         }
 
-                     }
 
-                     catch (error) {
 
-                         console.log("EEE", error);
 
-                     }
 
-                     this.once("block", listener);
 
-                 });
 
-                 if (timeout != null) {
 
-                     timer = setTimeout(() => {
 
-                         if (timer == null) {
 
-                             return;
 
-                         }
 
-                         timer = null;
 
-                         this.off("block", listener);
 
-                         reject(makeError("timeout", "TIMEOUT", { reason: "timeout" }));
 
-                     }, timeout);
 
-                 }
 
-                 listener(await this.getBlockNumber());
 
-             });
 
-         }
 
-         async waitForBlock(blockTag) {
 
-             assert(false, "not implemented yet", "NOT_IMPLEMENTED", {
 
-                 operation: "waitForBlock"
 
-             });
 
-         }
 
-         /**
 
-          *  Clear a timer created using the [[_setTimeout]] method.
 
-          */
 
-         _clearTimeout(timerId) {
 
-             const timer = this.#timers.get(timerId);
 
-             if (!timer) {
 
-                 return;
 
-             }
 
-             if (timer.timer) {
 
-                 clearTimeout(timer.timer);
 
-             }
 
-             this.#timers.delete(timerId);
 
-         }
 
-         /**
 
-          *  Create a timer that will execute %%func%% after at least %%timeout%%
 
-          *  (in ms). If %%timeout%% is unspecified, then %%func%% will execute
 
-          *  in the next event loop.
 
-          *
 
-          *  [Pausing](AbstractProvider-paused) the provider will pause any
 
-          *  associated timers.
 
-          */
 
-         _setTimeout(_func, timeout) {
 
-             if (timeout == null) {
 
-                 timeout = 0;
 
-             }
 
-             const timerId = this.#nextTimer++;
 
-             const func = () => {
 
-                 this.#timers.delete(timerId);
 
-                 _func();
 
-             };
 
-             if (this.paused) {
 
-                 this.#timers.set(timerId, { timer: null, func, time: timeout });
 
-             }
 
-             else {
 
-                 const timer = setTimeout(func, timeout);
 
-                 this.#timers.set(timerId, { timer, func, time: getTime$1() });
 
-             }
 
-             return timerId;
 
-         }
 
-         /**
 
-          *  Perform %%func%% on each subscriber.
 
-          */
 
-         _forEachSubscriber(func) {
 
-             for (const sub of this.#subs.values()) {
 
-                 func(sub.subscriber);
 
-             }
 
-         }
 
-         /**
 
-          *  Sub-classes may override this to customize subscription
 
-          *  implementations.
 
-          */
 
-         _getSubscriber(sub) {
 
-             switch (sub.type) {
 
-                 case "debug":
 
-                 case "error":
 
-                 case "network":
 
-                     return new UnmanagedSubscriber(sub.type);
 
-                 case "block": {
 
-                     const subscriber = new PollingBlockSubscriber(this);
 
-                     subscriber.pollingInterval = this.pollingInterval;
 
-                     return subscriber;
 
-                 }
 
-                 case "safe":
 
-                 case "finalized":
 
-                     return new PollingBlockTagSubscriber(this, sub.type);
 
-                 case "event":
 
-                     return new PollingEventSubscriber(this, sub.filter);
 
-                 case "transaction":
 
-                     return new PollingTransactionSubscriber(this, sub.hash);
 
-                 case "orphan":
 
-                     return new PollingOrphanSubscriber(this, sub.filter);
 
-             }
 
-             throw new Error(`unsupported event: ${sub.type}`);
 
-         }
 
-         /**
 
-          *  If a [[Subscriber]] fails and needs to replace itself, this
 
-          *  method may be used.
 
-          *
 
-          *  For example, this is used for providers when using the
 
-          *  ``eth_getFilterChanges`` method, which can return null if state
 
-          *  filters are not supported by the backend, allowing the Subscriber
 
-          *  to swap in a [[PollingEventSubscriber]].
 
-          */
 
-         _recoverSubscriber(oldSub, newSub) {
 
-             for (const sub of this.#subs.values()) {
 
-                 if (sub.subscriber === oldSub) {
 
-                     if (sub.started) {
 
-                         sub.subscriber.stop();
 
-                     }
 
-                     sub.subscriber = newSub;
 
-                     if (sub.started) {
 
-                         newSub.start();
 
-                     }
 
-                     if (this.#pausedState != null) {
 
-                         newSub.pause(this.#pausedState);
 
-                     }
 
-                     break;
 
-                 }
 
-             }
 
-         }
 
-         async #hasSub(event, emitArgs) {
 
-             let sub = await getSubscription(event, this);
 
-             // This is a log that is removing an existing log; we actually want
 
-             // to emit an orphan event for the removed log
 
-             if (sub.type === "event" && emitArgs && emitArgs.length > 0 && emitArgs[0].removed === true) {
 
-                 sub = await getSubscription({ orphan: "drop-log", log: emitArgs[0] }, this);
 
-             }
 
-             return this.#subs.get(sub.tag) || null;
 
-         }
 
-         async #getSub(event) {
 
-             const subscription = await getSubscription(event, this);
 
-             // Prevent tampering with our tag in any subclass' _getSubscriber
 
-             const tag = subscription.tag;
 
-             let sub = this.#subs.get(tag);
 
-             if (!sub) {
 
-                 const subscriber = this._getSubscriber(subscription);
 
-                 const addressableMap = new WeakMap();
 
-                 const nameMap = new Map();
 
-                 sub = { subscriber, tag, addressableMap, nameMap, started: false, listeners: [] };
 
-                 this.#subs.set(tag, sub);
 
-             }
 
-             return sub;
 
-         }
 
-         async on(event, listener) {
 
-             const sub = await this.#getSub(event);
 
-             sub.listeners.push({ listener, once: false });
 
-             if (!sub.started) {
 
-                 sub.subscriber.start();
 
-                 sub.started = true;
 
-                 if (this.#pausedState != null) {
 
-                     sub.subscriber.pause(this.#pausedState);
 
-                 }
 
-             }
 
-             return this;
 
-         }
 
-         async once(event, listener) {
 
-             const sub = await this.#getSub(event);
 
-             sub.listeners.push({ listener, once: true });
 
-             if (!sub.started) {
 
-                 sub.subscriber.start();
 
-                 sub.started = true;
 
-                 if (this.#pausedState != null) {
 
-                     sub.subscriber.pause(this.#pausedState);
 
-                 }
 
-             }
 
-             return this;
 
-         }
 
-         async emit(event, ...args) {
 
-             const sub = await this.#hasSub(event, args);
 
-             // If there is not subscription or if a recent emit removed
 
-             // the last of them (which also deleted the sub) do nothing
 
-             if (!sub || sub.listeners.length === 0) {
 
-                 return false;
 
-             }
 
-             const count = sub.listeners.length;
 
-             sub.listeners = sub.listeners.filter(({ listener, once }) => {
 
-                 const payload = new EventPayload(this, (once ? null : listener), event);
 
-                 try {
 
-                     listener.call(this, ...args, payload);
 
-                 }
 
-                 catch (error) { }
 
-                 return !once;
 
-             });
 
-             if (sub.listeners.length === 0) {
 
-                 if (sub.started) {
 
-                     sub.subscriber.stop();
 
-                 }
 
-                 this.#subs.delete(sub.tag);
 
-             }
 
-             return (count > 0);
 
-         }
 
-         async listenerCount(event) {
 
-             if (event) {
 
-                 const sub = await this.#hasSub(event);
 
-                 if (!sub) {
 
-                     return 0;
 
-                 }
 
-                 return sub.listeners.length;
 
-             }
 
-             let total = 0;
 
-             for (const { listeners } of this.#subs.values()) {
 
-                 total += listeners.length;
 
-             }
 
-             return total;
 
-         }
 
-         async listeners(event) {
 
-             if (event) {
 
-                 const sub = await this.#hasSub(event);
 
-                 if (!sub) {
 
-                     return [];
 
-                 }
 
-                 return sub.listeners.map(({ listener }) => listener);
 
-             }
 
-             let result = [];
 
-             for (const { listeners } of this.#subs.values()) {
 
-                 result = result.concat(listeners.map(({ listener }) => listener));
 
-             }
 
-             return result;
 
-         }
 
-         async off(event, listener) {
 
-             const sub = await this.#hasSub(event);
 
-             if (!sub) {
 
-                 return this;
 
-             }
 
-             if (listener) {
 
-                 const index = sub.listeners.map(({ listener }) => listener).indexOf(listener);
 
-                 if (index >= 0) {
 
-                     sub.listeners.splice(index, 1);
 
-                 }
 
-             }
 
-             if (!listener || sub.listeners.length === 0) {
 
-                 if (sub.started) {
 
-                     sub.subscriber.stop();
 
-                 }
 
-                 this.#subs.delete(sub.tag);
 
-             }
 
-             return this;
 
-         }
 
-         async removeAllListeners(event) {
 
-             if (event) {
 
-                 const { tag, started, subscriber } = await this.#getSub(event);
 
-                 if (started) {
 
-                     subscriber.stop();
 
-                 }
 
-                 this.#subs.delete(tag);
 
-             }
 
-             else {
 
-                 for (const [tag, { started, subscriber }] of this.#subs) {
 
-                     if (started) {
 
-                         subscriber.stop();
 
-                     }
 
-                     this.#subs.delete(tag);
 
-                 }
 
-             }
 
-             return this;
 
-         }
 
-         // Alias for "on"
 
-         async addListener(event, listener) {
 
-             return await this.on(event, listener);
 
-         }
 
-         // Alias for "off"
 
-         async removeListener(event, listener) {
 
-             return this.off(event, listener);
 
-         }
 
-         /**
 
-          *  If this provider has been destroyed using the [[destroy]] method.
 
-          *
 
-          *  Once destroyed, all resources are reclaimed, internal event loops
 
-          *  and timers are cleaned up and no further requests may be sent to
 
-          *  the provider.
 
-          */
 
-         get destroyed() {
 
-             return this.#destroyed;
 
-         }
 
-         /**
 
-          *  Sub-classes may use this to shutdown any sockets or release their
 
-          *  resources and reject any pending requests.
 
-          *
 
-          *  Sub-classes **must** call ``super.destroy()``.
 
-          */
 
-         destroy() {
 
-             // Stop all listeners
 
-             this.removeAllListeners();
 
-             // Shut down all tiemrs
 
-             for (const timerId of this.#timers.keys()) {
 
-                 this._clearTimeout(timerId);
 
-             }
 
-             this.#destroyed = true;
 
-         }
 
-         /**
 
-          *  Whether the provider is currently paused.
 
-          *
 
-          *  A paused provider will not emit any events, and generally should
 
-          *  not make any requests to the network, but that is up to sub-classes
 
-          *  to manage.
 
-          *
 
-          *  Setting ``paused = true`` is identical to calling ``.pause(false)``,
 
-          *  which will buffer any events that occur while paused until the
 
-          *  provider is unpaused.
 
-          */
 
-         get paused() { return (this.#pausedState != null); }
 
-         set paused(pause) {
 
-             if (!!pause === this.paused) {
 
-                 return;
 
-             }
 
-             if (this.paused) {
 
-                 this.resume();
 
-             }
 
-             else {
 
-                 this.pause(false);
 
-             }
 
-         }
 
-         /**
 
-          *  Pause the provider. If %%dropWhilePaused%%, any events that occur
 
-          *  while paused are dropped, otherwise all events will be emitted once
 
-          *  the provider is unpaused.
 
-          */
 
-         pause(dropWhilePaused) {
 
-             this.#lastBlockNumber = -1;
 
-             if (this.#pausedState != null) {
 
-                 if (this.#pausedState == !!dropWhilePaused) {
 
-                     return;
 
-                 }
 
-                 assert(false, "cannot change pause type; resume first", "UNSUPPORTED_OPERATION", {
 
-                     operation: "pause"
 
-                 });
 
-             }
 
-             this._forEachSubscriber((s) => s.pause(dropWhilePaused));
 
-             this.#pausedState = !!dropWhilePaused;
 
-             for (const timer of this.#timers.values()) {
 
-                 // Clear the timer
 
-                 if (timer.timer) {
 
-                     clearTimeout(timer.timer);
 
-                 }
 
-                 // Remaining time needed for when we become unpaused
 
-                 timer.time = getTime$1() - timer.time;
 
-             }
 
-         }
 
-         /**
 
-          *  Resume the provider.
 
-          */
 
-         resume() {
 
-             if (this.#pausedState == null) {
 
-                 return;
 
-             }
 
-             this._forEachSubscriber((s) => s.resume());
 
-             this.#pausedState = null;
 
-             for (const timer of this.#timers.values()) {
 
-                 // Remaining time when we were paused
 
-                 let timeout = timer.time;
 
-                 if (timeout < 0) {
 
-                     timeout = 0;
 
-                 }
 
-                 // Start time (in cause paused, so we con compute remaininf time)
 
-                 timer.time = getTime$1();
 
-                 // Start the timer
 
-                 setTimeout(timer.func, timeout);
 
-             }
 
-         }
 
-     }
 
-     function _parseString(result, start) {
 
-         try {
 
-             const bytes = _parseBytes(result, start);
 
-             if (bytes) {
 
-                 return toUtf8String(bytes);
 
-             }
 
-         }
 
-         catch (error) { }
 
-         return null;
 
-     }
 
-     function _parseBytes(result, start) {
 
-         if (result === "0x") {
 
-             return null;
 
-         }
 
-         try {
 
-             const offset = getNumber(dataSlice(result, start, start + 32));
 
-             const length = getNumber(dataSlice(result, offset, offset + 32));
 
-             return dataSlice(result, offset + 32, offset + 32 + length);
 
-         }
 
-         catch (error) { }
 
-         return null;
 
-     }
 
-     function numPad(value) {
 
-         const result = toBeArray(value);
 
-         if (result.length > 32) {
 
-             throw new Error("internal; should not happen");
 
-         }
 
-         const padded = new Uint8Array(32);
 
-         padded.set(result, 32 - result.length);
 
-         return padded;
 
-     }
 
-     function bytesPad(value) {
 
-         if ((value.length % 32) === 0) {
 
-             return value;
 
-         }
 
-         const result = new Uint8Array(Math.ceil(value.length / 32) * 32);
 
-         result.set(value);
 
-         return result;
 
-     }
 
-     const empty = new Uint8Array([]);
 
-     // ABI Encodes a series of (bytes, bytes, ...)
 
-     function encodeBytes(datas) {
 
-         const result = [];
 
-         let byteCount = 0;
 
-         // Add place-holders for pointers as we add items
 
-         for (let i = 0; i < datas.length; i++) {
 
-             result.push(empty);
 
-             byteCount += 32;
 
-         }
 
-         for (let i = 0; i < datas.length; i++) {
 
-             const data = getBytes(datas[i]);
 
-             // Update the bytes offset
 
-             result[i] = numPad(byteCount);
 
-             // The length and padded value of data
 
-             result.push(numPad(data.length));
 
-             result.push(bytesPad(data));
 
-             byteCount += 32 + Math.ceil(data.length / 32) * 32;
 
-         }
 
-         return concat(result);
 
-     }
 
-     const zeros = "0x0000000000000000000000000000000000000000000000000000000000000000";
 
-     function parseOffchainLookup(data) {
 
-         const result = {
 
-             sender: "", urls: [], calldata: "", selector: "", extraData: "", errorArgs: []
 
-         };
 
-         assert(dataLength(data) >= 5 * 32, "insufficient OffchainLookup data", "OFFCHAIN_FAULT", {
 
-             reason: "insufficient OffchainLookup data"
 
-         });
 
-         const sender = dataSlice(data, 0, 32);
 
-         assert(dataSlice(sender, 0, 12) === dataSlice(zeros, 0, 12), "corrupt OffchainLookup sender", "OFFCHAIN_FAULT", {
 
-             reason: "corrupt OffchainLookup sender"
 
-         });
 
-         result.sender = dataSlice(sender, 12);
 
-         // Read the URLs from the response
 
-         try {
 
-             const urls = [];
 
-             const urlsOffset = getNumber(dataSlice(data, 32, 64));
 
-             const urlsLength = getNumber(dataSlice(data, urlsOffset, urlsOffset + 32));
 
-             const urlsData = dataSlice(data, urlsOffset + 32);
 
-             for (let u = 0; u < urlsLength; u++) {
 
-                 const url = _parseString(urlsData, u * 32);
 
-                 if (url == null) {
 
-                     throw new Error("abort");
 
-                 }
 
-                 urls.push(url);
 
-             }
 
-             result.urls = urls;
 
-         }
 
-         catch (error) {
 
-             assert(false, "corrupt OffchainLookup urls", "OFFCHAIN_FAULT", {
 
-                 reason: "corrupt OffchainLookup urls"
 
-             });
 
-         }
 
-         // Get the CCIP calldata to forward
 
-         try {
 
-             const calldata = _parseBytes(data, 64);
 
-             if (calldata == null) {
 
-                 throw new Error("abort");
 
-             }
 
-             result.calldata = calldata;
 
-         }
 
-         catch (error) {
 
-             assert(false, "corrupt OffchainLookup calldata", "OFFCHAIN_FAULT", {
 
-                 reason: "corrupt OffchainLookup calldata"
 
-             });
 
-         }
 
-         // Get the callbackSelector (bytes4)
 
-         assert(dataSlice(data, 100, 128) === dataSlice(zeros, 0, 28), "corrupt OffchainLookup callbaackSelector", "OFFCHAIN_FAULT", {
 
-             reason: "corrupt OffchainLookup callbaackSelector"
 
-         });
 
-         result.selector = dataSlice(data, 96, 100);
 
-         // Get the extra data to send back to the contract as context
 
-         try {
 
-             const extraData = _parseBytes(data, 128);
 
-             if (extraData == null) {
 
-                 throw new Error("abort");
 
-             }
 
-             result.extraData = extraData;
 
-         }
 
-         catch (error) {
 
-             assert(false, "corrupt OffchainLookup extraData", "OFFCHAIN_FAULT", {
 
-                 reason: "corrupt OffchainLookup extraData"
 
-             });
 
-         }
 
-         result.errorArgs = "sender,urls,calldata,selector,extraData".split(/,/).map((k) => result[k]);
 
-         return result;
 
-     }
 
-     /**
 
-      *  Generally the [[Wallet]] and [[JsonRpcSigner]] and their sub-classes
 
-      *  are sufficent for most developers, but this is provided to
 
-      *  fascilitate more complex Signers.
 
-      *
 
-      *  @_section: api/providers/abstract-signer: Subclassing Signer [abstract-signer]
 
-      */
 
-     function checkProvider(signer, operation) {
 
-         if (signer.provider) {
 
-             return signer.provider;
 
-         }
 
-         assert(false, "missing provider", "UNSUPPORTED_OPERATION", { operation });
 
-     }
 
-     async function populate(signer, tx) {
 
-         let pop = copyRequest(tx);
 
-         if (pop.to != null) {
 
-             pop.to = resolveAddress(pop.to, signer);
 
-         }
 
-         if (pop.from != null) {
 
-             const from = pop.from;
 
-             pop.from = Promise.all([
 
-                 signer.getAddress(),
 
-                 resolveAddress(from, signer)
 
-             ]).then(([address, from]) => {
 
-                 assertArgument(address.toLowerCase() === from.toLowerCase(), "transaction from mismatch", "tx.from", from);
 
-                 return address;
 
-             });
 
-         }
 
-         else {
 
-             pop.from = signer.getAddress();
 
-         }
 
-         return await resolveProperties(pop);
 
-     }
 
-     /**
 
-      *  An **AbstractSigner** includes most of teh functionality required
 
-      *  to get a [[Signer]] working as expected, but requires a few
 
-      *  Signer-specific methods be overridden.
 
-      *
 
-      */
 
-     class AbstractSigner {
 
-         /**
 
-          *  The provider this signer is connected to.
 
-          */
 
-         provider;
 
-         /**
 
-          *  Creates a new Signer connected to %%provider%%.
 
-          */
 
-         constructor(provider) {
 
-             defineProperties(this, { provider: (provider || null) });
 
-         }
 
-         async getNonce(blockTag) {
 
-             return checkProvider(this, "getTransactionCount").getTransactionCount(await this.getAddress(), blockTag);
 
-         }
 
-         async populateCall(tx) {
 
-             const pop = await populate(this, tx);
 
-             return pop;
 
-         }
 
-         async populateTransaction(tx) {
 
-             const provider = checkProvider(this, "populateTransaction");
 
-             const pop = await populate(this, tx);
 
-             if (pop.nonce == null) {
 
-                 pop.nonce = await this.getNonce("pending");
 
-             }
 
-             if (pop.gasLimit == null) {
 
-                 pop.gasLimit = await this.estimateGas(pop);
 
-             }
 
-             // Populate the chain ID
 
-             const network = await (this.provider).getNetwork();
 
-             if (pop.chainId != null) {
 
-                 const chainId = getBigInt(pop.chainId);
 
-                 assertArgument(chainId === network.chainId, "transaction chainId mismatch", "tx.chainId", tx.chainId);
 
-             }
 
-             else {
 
-                 pop.chainId = network.chainId;
 
-             }
 
-             // Do not allow mixing pre-eip-1559 and eip-1559 properties
 
-             const hasEip1559 = (pop.maxFeePerGas != null || pop.maxPriorityFeePerGas != null);
 
-             if (pop.gasPrice != null && (pop.type === 2 || hasEip1559)) {
 
-                 assertArgument(false, "eip-1559 transaction do not support gasPrice", "tx", tx);
 
-             }
 
-             else if ((pop.type === 0 || pop.type === 1) && hasEip1559) {
 
-                 assertArgument(false, "pre-eip-1559 transaction do not support maxFeePerGas/maxPriorityFeePerGas", "tx", tx);
 
-             }
 
-             if ((pop.type === 2 || pop.type == null) && (pop.maxFeePerGas != null && pop.maxPriorityFeePerGas != null)) {
 
-                 // Fully-formed EIP-1559 transaction (skip getFeeData)
 
-                 pop.type = 2;
 
-             }
 
-             else if (pop.type === 0 || pop.type === 1) {
 
-                 // Explicit Legacy or EIP-2930 transaction
 
-                 // We need to get fee data to determine things
 
-                 const feeData = await provider.getFeeData();
 
-                 assert(feeData.gasPrice != null, "network does not support gasPrice", "UNSUPPORTED_OPERATION", {
 
-                     operation: "getGasPrice"
 
-                 });
 
-                 // Populate missing gasPrice
 
-                 if (pop.gasPrice == null) {
 
-                     pop.gasPrice = feeData.gasPrice;
 
-                 }
 
-             }
 
-             else {
 
-                 // We need to get fee data to determine things
 
-                 const feeData = await provider.getFeeData();
 
-                 if (pop.type == null) {
 
-                     // We need to auto-detect the intended type of this transaction...
 
-                     if (feeData.maxFeePerGas != null && feeData.maxPriorityFeePerGas != null) {
 
-                         // The network supports EIP-1559!
 
-                         // Upgrade transaction from null to eip-1559
 
-                         pop.type = 2;
 
-                         if (pop.gasPrice != null) {
 
-                             // Using legacy gasPrice property on an eip-1559 network,
 
-                             // so use gasPrice as both fee properties
 
-                             const gasPrice = pop.gasPrice;
 
-                             delete pop.gasPrice;
 
-                             pop.maxFeePerGas = gasPrice;
 
-                             pop.maxPriorityFeePerGas = gasPrice;
 
-                         }
 
-                         else {
 
-                             // Populate missing fee data
 
-                             if (pop.maxFeePerGas == null) {
 
-                                 pop.maxFeePerGas = feeData.maxFeePerGas;
 
-                             }
 
-                             if (pop.maxPriorityFeePerGas == null) {
 
-                                 pop.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas;
 
-                             }
 
-                         }
 
-                     }
 
-                     else if (feeData.gasPrice != null) {
 
-                         // Network doesn't support EIP-1559...
 
-                         // ...but they are trying to use EIP-1559 properties
 
-                         assert(!hasEip1559, "network does not support EIP-1559", "UNSUPPORTED_OPERATION", {
 
-                             operation: "populateTransaction"
 
-                         });
 
-                         // Populate missing fee data
 
-                         if (pop.gasPrice == null) {
 
-                             pop.gasPrice = feeData.gasPrice;
 
-                         }
 
-                         // Explicitly set untyped transaction to legacy
 
-                         // @TODO: Maybe this shold allow type 1?
 
-                         pop.type = 0;
 
-                     }
 
-                     else {
 
-                         // getFeeData has failed us.
 
-                         assert(false, "failed to get consistent fee data", "UNSUPPORTED_OPERATION", {
 
-                             operation: "signer.getFeeData"
 
-                         });
 
-                     }
 
-                 }
 
-                 else if (pop.type === 2 || pop.type === 3) {
 
-                     // Explicitly using EIP-1559 or EIP-4844
 
-                     // Populate missing fee data
 
-                     if (pop.maxFeePerGas == null) {
 
-                         pop.maxFeePerGas = feeData.maxFeePerGas;
 
-                     }
 
-                     if (pop.maxPriorityFeePerGas == null) {
 
-                         pop.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas;
 
-                     }
 
-                 }
 
-             }
 
-             //@TOOD: Don't await all over the place; save them up for
 
-             // the end for better batching
 
-             return await resolveProperties(pop);
 
-         }
 
-         async estimateGas(tx) {
 
-             return checkProvider(this, "estimateGas").estimateGas(await this.populateCall(tx));
 
-         }
 
-         async call(tx) {
 
-             return checkProvider(this, "call").call(await this.populateCall(tx));
 
-         }
 
-         async resolveName(name) {
 
-             const provider = checkProvider(this, "resolveName");
 
-             return await provider.resolveName(name);
 
-         }
 
-         async sendTransaction(tx) {
 
-             const provider = checkProvider(this, "sendTransaction");
 
-             const pop = await this.populateTransaction(tx);
 
-             delete pop.from;
 
-             const txObj = Transaction.from(pop);
 
-             return await provider.broadcastTransaction(await this.signTransaction(txObj));
 
-         }
 
-     }
 
-     /**
 
-      *  A **VoidSigner** is a class deisgned to allow an address to be used
 
-      *  in any API which accepts a Signer, but for which there are no
 
-      *  credentials available to perform any actual signing.
 
-      *
 
-      *  This for example allow impersonating an account for the purpose of
 
-      *  static calls or estimating gas, but does not allow sending transactions.
 
-      */
 
-     class VoidSigner extends AbstractSigner {
 
-         /**
 
-          *  The signer address.
 
-          */
 
-         address;
 
-         /**
 
-          *  Creates a new **VoidSigner** with %%address%% attached to
 
-          *  %%provider%%.
 
-          */
 
-         constructor(address, provider) {
 
-             super(provider);
 
-             defineProperties(this, { address });
 
-         }
 
-         async getAddress() { return this.address; }
 
-         connect(provider) {
 
-             return new VoidSigner(this.address, provider);
 
-         }
 
-         #throwUnsupported(suffix, operation) {
 
-             assert(false, `VoidSigner cannot sign ${suffix}`, "UNSUPPORTED_OPERATION", { operation });
 
-         }
 
-         async signTransaction(tx) {
 
-             this.#throwUnsupported("transactions", "signTransaction");
 
-         }
 
-         async signMessage(message) {
 
-             this.#throwUnsupported("messages", "signMessage");
 
-         }
 
-         async signTypedData(domain, types, value) {
 
-             this.#throwUnsupported("typed-data", "signTypedData");
 
-         }
 
-     }
 
-     /**
 
-      *  There are many awesome community services that provide Ethereum
 
-      *  nodes both for developers just starting out and for large-scale
 
-      *  communities.
 
-      *
 
-      *  @_section: api/providers/thirdparty: Community Providers  [thirdparty]
 
-      */
 
-     // Show the throttle message only once per service
 
-     const shown = new Set();
 
-     /**
 
-      *  Displays a warning in tht console when the community resource is
 
-      *  being used too heavily by the app, recommending the developer
 
-      *  acquire their own credentials instead of using the community
 
-      *  credentials.
 
-      *
 
-      *  The notification will only occur once per service.
 
-      */
 
-     function showThrottleMessage(service) {
 
-         if (shown.has(service)) {
 
-             return;
 
-         }
 
-         shown.add(service);
 
-         console.log("========= NOTICE =========");
 
-         console.log(`Request-Rate Exceeded for ${service} (this message will not be repeated)`);
 
-         console.log("");
 
-         console.log("The default API keys for each service are provided as a highly-throttled,");
 
-         console.log("community resource for low-traffic projects and early prototyping.");
 
-         console.log("");
 
-         console.log("While your application will continue to function, we highly recommended");
 
-         console.log("signing up for your own API keys to improve performance, increase your");
 
-         console.log("request rate/limit and enable other perks, such as metrics and advanced APIs.");
 
-         console.log("");
 
-         console.log("For more details: https:/\/docs.ethers.org/api-keys/");
 
-         console.log("==========================");
 
-     }
 
-     function copy(obj) {
 
-         return JSON.parse(JSON.stringify(obj));
 
-     }
 
-     /**
 
-      *  Some backends support subscribing to events using a Filter ID.
 
-      *
 
-      *  When subscribing with this technique, the node issues a unique
 
-      *  //Filter ID//. At this point the node dedicates resources to
 
-      *  the filter, so that periodic calls to follow up on the //Filter ID//
 
-      *  will receive any events since the last call.
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class FilterIdSubscriber {
 
-         #provider;
 
-         #filterIdPromise;
 
-         #poller;
 
-         #running;
 
-         #network;
 
-         #hault;
 
-         /**
 
-          *  Creates a new **FilterIdSubscriber** which will used [[_subscribe]]
 
-          *  and [[_emitResults]] to setup the subscription and provide the event
 
-          *  to the %%provider%%.
 
-          */
 
-         constructor(provider) {
 
-             this.#provider = provider;
 
-             this.#filterIdPromise = null;
 
-             this.#poller = this.#poll.bind(this);
 
-             this.#running = false;
 
-             this.#network = null;
 
-             this.#hault = false;
 
-         }
 
-         /**
 
-          *  Sub-classes **must** override this to begin the subscription.
 
-          */
 
-         _subscribe(provider) {
 
-             throw new Error("subclasses must override this");
 
-         }
 
-         /**
 
-          *  Sub-classes **must** override this handle the events.
 
-          */
 
-         _emitResults(provider, result) {
 
-             throw new Error("subclasses must override this");
 
-         }
 
-         /**
 
-          *  Sub-classes **must** override this handle recovery on errors.
 
-          */
 
-         _recover(provider) {
 
-             throw new Error("subclasses must override this");
 
-         }
 
-         async #poll(blockNumber) {
 
-             try {
 
-                 // Subscribe if necessary
 
-                 if (this.#filterIdPromise == null) {
 
-                     this.#filterIdPromise = this._subscribe(this.#provider);
 
-                 }
 
-                 // Get the Filter ID
 
-                 let filterId = null;
 
-                 try {
 
-                     filterId = await this.#filterIdPromise;
 
-                 }
 
-                 catch (error) {
 
-                     if (!isError(error, "UNSUPPORTED_OPERATION") || error.operation !== "eth_newFilter") {
 
-                         throw error;
 
-                     }
 
-                 }
 
-                 // The backend does not support Filter ID; downgrade to
 
-                 // polling
 
-                 if (filterId == null) {
 
-                     this.#filterIdPromise = null;
 
-                     this.#provider._recoverSubscriber(this, this._recover(this.#provider));
 
-                     return;
 
-                 }
 
-                 const network = await this.#provider.getNetwork();
 
-                 if (!this.#network) {
 
-                     this.#network = network;
 
-                 }
 
-                 if (this.#network.chainId !== network.chainId) {
 
-                     throw new Error("chaid changed");
 
-                 }
 
-                 if (this.#hault) {
 
-                     return;
 
-                 }
 
-                 const result = await this.#provider.send("eth_getFilterChanges", [filterId]);
 
-                 await this._emitResults(this.#provider, result);
 
-             }
 
-             catch (error) {
 
-                 console.log("@TODO", error);
 
-             }
 
-             this.#provider.once("block", this.#poller);
 
-         }
 
-         #teardown() {
 
-             const filterIdPromise = this.#filterIdPromise;
 
-             if (filterIdPromise) {
 
-                 this.#filterIdPromise = null;
 
-                 filterIdPromise.then((filterId) => {
 
-                     if (this.#provider.destroyed) {
 
-                         return;
 
-                     }
 
-                     this.#provider.send("eth_uninstallFilter", [filterId]);
 
-                 });
 
-             }
 
-         }
 
-         start() {
 
-             if (this.#running) {
 
-                 return;
 
-             }
 
-             this.#running = true;
 
-             this.#poll(-2);
 
-         }
 
-         stop() {
 
-             if (!this.#running) {
 
-                 return;
 
-             }
 
-             this.#running = false;
 
-             this.#hault = true;
 
-             this.#teardown();
 
-             this.#provider.off("block", this.#poller);
 
-         }
 
-         pause(dropWhilePaused) {
 
-             if (dropWhilePaused) {
 
-                 this.#teardown();
 
-             }
 
-             this.#provider.off("block", this.#poller);
 
-         }
 
-         resume() { this.start(); }
 
-     }
 
-     /**
 
-      *  A **FilterIdSubscriber** for receiving contract events.
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class FilterIdEventSubscriber extends FilterIdSubscriber {
 
-         #event;
 
-         /**
 
-          *  Creates a new **FilterIdEventSubscriber** attached to %%provider%%
 
-          *  listening for %%filter%%.
 
-          */
 
-         constructor(provider, filter) {
 
-             super(provider);
 
-             this.#event = copy(filter);
 
-         }
 
-         _recover(provider) {
 
-             return new PollingEventSubscriber(provider, this.#event);
 
-         }
 
-         async _subscribe(provider) {
 
-             const filterId = await provider.send("eth_newFilter", [this.#event]);
 
-             return filterId;
 
-         }
 
-         async _emitResults(provider, results) {
 
-             for (const result of results) {
 
-                 provider.emit(this.#event, provider._wrapLog(result, provider._network));
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      *  A **FilterIdSubscriber** for receiving pending transactions events.
 
-      *
 
-      *  @_docloc: api/providers/abstract-provider
 
-      */
 
-     class FilterIdPendingSubscriber extends FilterIdSubscriber {
 
-         async _subscribe(provider) {
 
-             return await provider.send("eth_newPendingTransactionFilter", []);
 
-         }
 
-         async _emitResults(provider, results) {
 
-             for (const result of results) {
 
-                 provider.emit("pending", result);
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      *  One of the most common ways to interact with the blockchain is
 
-      *  by a node running a JSON-RPC interface which can be connected to,
 
-      *  based on the transport, using:
 
-      *
 
-      *  - HTTP or HTTPS - [[JsonRpcProvider]]
 
-      *  - WebSocket - [[WebSocketProvider]]
 
-      *  - IPC - [[IpcSocketProvider]]
 
-      *
 
-      * @_section: api/providers/jsonrpc:JSON-RPC Provider  [about-jsonrpcProvider]
 
-      */
 
-     // @TODO:
 
-     // - Add the batching API
 
-     // https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/ethereum/eth1.0-apis/assembled-spec/openrpc.json&uiSchema%5BappBar%5D%5Bui:splitView%5D=true&uiSchema%5BappBar%5D%5Bui:input%5D=false&uiSchema%5BappBar%5D%5Bui:examplesDropdown%5D=false
 
-     const Primitive = "bigint,boolean,function,number,string,symbol".split(/,/g);
 
-     //const Methods = "getAddress,then".split(/,/g);
 
-     function deepCopy(value) {
 
-         if (value == null || Primitive.indexOf(typeof (value)) >= 0) {
 
-             return value;
 
-         }
 
-         // Keep any Addressable
 
-         if (typeof (value.getAddress) === "function") {
 
-             return value;
 
-         }
 
-         if (Array.isArray(value)) {
 
-             return (value.map(deepCopy));
 
-         }
 
-         if (typeof (value) === "object") {
 
-             return Object.keys(value).reduce((accum, key) => {
 
-                 accum[key] = value[key];
 
-                 return accum;
 
-             }, {});
 
-         }
 
-         throw new Error(`should not happen: ${value} (${typeof (value)})`);
 
-     }
 
-     function stall$3(duration) {
 
-         return new Promise((resolve) => { setTimeout(resolve, duration); });
 
-     }
 
-     function getLowerCase(value) {
 
-         if (value) {
 
-             return value.toLowerCase();
 
-         }
 
-         return value;
 
-     }
 
-     function isPollable(value) {
 
-         return (value && typeof (value.pollingInterval) === "number");
 
-     }
 
-     const defaultOptions = {
 
-         polling: false,
 
-         staticNetwork: null,
 
-         batchStallTime: 10,
 
-         batchMaxSize: (1 << 20),
 
-         batchMaxCount: 100,
 
-         cacheTimeout: 250,
 
-         pollingInterval: 4000
 
-     };
 
-     // @TODO: Unchecked Signers
 
-     class JsonRpcSigner extends AbstractSigner {
 
-         address;
 
-         constructor(provider, address) {
 
-             super(provider);
 
-             address = getAddress(address);
 
-             defineProperties(this, { address });
 
-         }
 
-         connect(provider) {
 
-             assert(false, "cannot reconnect JsonRpcSigner", "UNSUPPORTED_OPERATION", {
 
-                 operation: "signer.connect"
 
-             });
 
-         }
 
-         async getAddress() {
 
-             return this.address;
 
-         }
 
-         // JSON-RPC will automatially fill in nonce, etc. so we just check from
 
-         async populateTransaction(tx) {
 
-             return await this.populateCall(tx);
 
-         }
 
-         // Returns just the hash of the transaction after sent, which is what
 
-         // the bare JSON-RPC API does;
 
-         async sendUncheckedTransaction(_tx) {
 
-             const tx = deepCopy(_tx);
 
-             const promises = [];
 
-             // Make sure the from matches the sender
 
-             if (tx.from) {
 
-                 const _from = tx.from;
 
-                 promises.push((async () => {
 
-                     const from = await resolveAddress(_from, this.provider);
 
-                     assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(), "from address mismatch", "transaction", _tx);
 
-                     tx.from = from;
 
-                 })());
 
-             }
 
-             else {
 
-                 tx.from = this.address;
 
-             }
 
-             // The JSON-RPC for eth_sendTransaction uses 90000 gas; if the user
 
-             // wishes to use this, it is easy to specify explicitly, otherwise
 
-             // we look it up for them.
 
-             if (tx.gasLimit == null) {
 
-                 promises.push((async () => {
 
-                     tx.gasLimit = await this.provider.estimateGas({ ...tx, from: this.address });
 
-                 })());
 
-             }
 
-             // The address may be an ENS name or Addressable
 
-             if (tx.to != null) {
 
-                 const _to = tx.to;
 
-                 promises.push((async () => {
 
-                     tx.to = await resolveAddress(_to, this.provider);
 
-                 })());
 
-             }
 
-             // Wait until all of our properties are filled in
 
-             if (promises.length) {
 
-                 await Promise.all(promises);
 
-             }
 
-             const hexTx = this.provider.getRpcTransaction(tx);
 
-             return this.provider.send("eth_sendTransaction", [hexTx]);
 
-         }
 
-         async sendTransaction(tx) {
 
-             // This cannot be mined any earlier than any recent block
 
-             const blockNumber = await this.provider.getBlockNumber();
 
-             // Send the transaction
 
-             const hash = await this.sendUncheckedTransaction(tx);
 
-             // Unfortunately, JSON-RPC only provides and opaque transaction hash
 
-             // for a response, and we need the actual transaction, so we poll
 
-             // for it; it should show up very quickly
 
-             return await (new Promise((resolve, reject) => {
 
-                 const timeouts = [1000, 100];
 
-                 let invalids = 0;
 
-                 const checkTx = async () => {
 
-                     try {
 
-                         // Try getting the transaction
 
-                         const tx = await this.provider.getTransaction(hash);
 
-                         if (tx != null) {
 
-                             resolve(tx.replaceableTransaction(blockNumber));
 
-                             return;
 
-                         }
 
-                     }
 
-                     catch (error) {
 
-                         // If we were cancelled: stop polling.
 
-                         // If the data is bad: the node returns bad transactions
 
-                         // If the network changed: calling again will also fail
 
-                         // If unsupported: likely destroyed
 
-                         if (isError(error, "CANCELLED") || isError(error, "BAD_DATA") ||
 
-                             isError(error, "NETWORK_ERROR") || isError(error, "UNSUPPORTED_OPERATION")) {
 
-                             if (error.info == null) {
 
-                                 error.info = {};
 
-                             }
 
-                             error.info.sendTransactionHash = hash;
 
-                             reject(error);
 
-                             return;
 
-                         }
 
-                         // Stop-gap for misbehaving backends; see #4513
 
-                         if (isError(error, "INVALID_ARGUMENT")) {
 
-                             invalids++;
 
-                             if (error.info == null) {
 
-                                 error.info = {};
 
-                             }
 
-                             error.info.sendTransactionHash = hash;
 
-                             if (invalids > 10) {
 
-                                 reject(error);
 
-                                 return;
 
-                             }
 
-                         }
 
-                         // Notify anyone that cares; but we will try again, since
 
-                         // it is likely an intermittent service error
 
-                         this.provider.emit("error", makeError("failed to fetch transation after sending (will try again)", "UNKNOWN_ERROR", { error }));
 
-                     }
 
-                     // Wait another 4 seconds
 
-                     this.provider._setTimeout(() => { checkTx(); }, timeouts.pop() || 4000);
 
-                 };
 
-                 checkTx();
 
-             }));
 
-         }
 
-         async signTransaction(_tx) {
 
-             const tx = deepCopy(_tx);
 
-             // Make sure the from matches the sender
 
-             if (tx.from) {
 
-                 const from = await resolveAddress(tx.from, this.provider);
 
-                 assertArgument(from != null && from.toLowerCase() === this.address.toLowerCase(), "from address mismatch", "transaction", _tx);
 
-                 tx.from = from;
 
-             }
 
-             else {
 
-                 tx.from = this.address;
 
-             }
 
-             const hexTx = this.provider.getRpcTransaction(tx);
 
-             return await this.provider.send("eth_signTransaction", [hexTx]);
 
-         }
 
-         async signMessage(_message) {
 
-             const message = ((typeof (_message) === "string") ? toUtf8Bytes(_message) : _message);
 
-             return await this.provider.send("personal_sign", [
 
-                 hexlify(message), this.address.toLowerCase()
 
-             ]);
 
-         }
 
-         async signTypedData(domain, types, _value) {
 
-             const value = deepCopy(_value);
 
-             // Populate any ENS names (in-place)
 
-             const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (value) => {
 
-                 const address = await resolveAddress(value);
 
-                 assertArgument(address != null, "TypedData does not support null address", "value", value);
 
-                 return address;
 
-             });
 
-             return await this.provider.send("eth_signTypedData_v4", [
 
-                 this.address.toLowerCase(),
 
-                 JSON.stringify(TypedDataEncoder.getPayload(populated.domain, types, populated.value))
 
-             ]);
 
-         }
 
-         async unlock(password) {
 
-             return this.provider.send("personal_unlockAccount", [
 
-                 this.address.toLowerCase(), password, null
 
-             ]);
 
-         }
 
-         // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
 
-         async _legacySignMessage(_message) {
 
-             const message = ((typeof (_message) === "string") ? toUtf8Bytes(_message) : _message);
 
-             return await this.provider.send("eth_sign", [
 
-                 this.address.toLowerCase(), hexlify(message)
 
-             ]);
 
-         }
 
-     }
 
-     /**
 
-      *  The JsonRpcApiProvider is an abstract class and **MUST** be
 
-      *  sub-classed.
 
-      *
 
-      *  It provides the base for all JSON-RPC-based Provider interaction.
 
-      *
 
-      *  Sub-classing Notes:
 
-      *  - a sub-class MUST override _send
 
-      *  - a sub-class MUST call the `_start()` method once connected
 
-      */
 
-     class JsonRpcApiProvider extends AbstractProvider {
 
-         #options;
 
-         // The next ID to use for the JSON-RPC ID field
 
-         #nextId;
 
-         // Payloads are queued and triggered in batches using the drainTimer
 
-         #payloads;
 
-         #drainTimer;
 
-         #notReady;
 
-         #network;
 
-         #pendingDetectNetwork;
 
-         #scheduleDrain() {
 
-             if (this.#drainTimer) {
 
-                 return;
 
-             }
 
-             // If we aren't using batching, no harm in sending it immediately
 
-             const stallTime = (this._getOption("batchMaxCount") === 1) ? 0 : this._getOption("batchStallTime");
 
-             this.#drainTimer = setTimeout(() => {
 
-                 this.#drainTimer = null;
 
-                 const payloads = this.#payloads;
 
-                 this.#payloads = [];
 
-                 while (payloads.length) {
 
-                     // Create payload batches that satisfy our batch constraints
 
-                     const batch = [(payloads.shift())];
 
-                     while (payloads.length) {
 
-                         if (batch.length === this.#options.batchMaxCount) {
 
-                             break;
 
-                         }
 
-                         batch.push((payloads.shift()));
 
-                         const bytes = JSON.stringify(batch.map((p) => p.payload));
 
-                         if (bytes.length > this.#options.batchMaxSize) {
 
-                             payloads.unshift((batch.pop()));
 
-                             break;
 
-                         }
 
-                     }
 
-                     // Process the result to each payload
 
-                     (async () => {
 
-                         const payload = ((batch.length === 1) ? batch[0].payload : batch.map((p) => p.payload));
 
-                         this.emit("debug", { action: "sendRpcPayload", payload });
 
-                         try {
 
-                             const result = await this._send(payload);
 
-                             this.emit("debug", { action: "receiveRpcResult", result });
 
-                             // Process results in batch order
 
-                             for (const { resolve, reject, payload } of batch) {
 
-                                 if (this.destroyed) {
 
-                                     reject(makeError("provider destroyed; cancelled request", "UNSUPPORTED_OPERATION", { operation: payload.method }));
 
-                                     continue;
 
-                                 }
 
-                                 // Find the matching result
 
-                                 const resp = result.filter((r) => (r.id === payload.id))[0];
 
-                                 // No result; the node failed us in unexpected ways
 
-                                 if (resp == null) {
 
-                                     const error = makeError("missing response for request", "BAD_DATA", {
 
-                                         value: result, info: { payload }
 
-                                     });
 
-                                     this.emit("error", error);
 
-                                     reject(error);
 
-                                     continue;
 
-                                 }
 
-                                 // The response is an error
 
-                                 if ("error" in resp) {
 
-                                     reject(this.getRpcError(payload, resp));
 
-                                     continue;
 
-                                 }
 
-                                 // All good; send the result
 
-                                 resolve(resp.result);
 
-                             }
 
-                         }
 
-                         catch (error) {
 
-                             this.emit("debug", { action: "receiveRpcError", error });
 
-                             for (const { reject } of batch) {
 
-                                 // @TODO: augment the error with the payload
 
-                                 reject(error);
 
-                             }
 
-                         }
 
-                     })();
 
-                 }
 
-             }, stallTime);
 
-         }
 
-         constructor(network, options) {
 
-             super(network, options);
 
-             this.#nextId = 1;
 
-             this.#options = Object.assign({}, defaultOptions, options || {});
 
-             this.#payloads = [];
 
-             this.#drainTimer = null;
 
-             this.#network = null;
 
-             this.#pendingDetectNetwork = null;
 
-             {
 
-                 let resolve = null;
 
-                 const promise = new Promise((_resolve) => {
 
-                     resolve = _resolve;
 
-                 });
 
-                 this.#notReady = { promise, resolve };
 
-             }
 
-             const staticNetwork = this._getOption("staticNetwork");
 
-             if (typeof (staticNetwork) === "boolean") {
 
-                 assertArgument(!staticNetwork || network !== "any", "staticNetwork cannot be used on special network 'any'", "options", options);
 
-                 if (staticNetwork && network != null) {
 
-                     this.#network = Network.from(network);
 
-                 }
 
-             }
 
-             else if (staticNetwork) {
 
-                 // Make sure any static network is compatbile with the provided netwrok
 
-                 assertArgument(network == null || staticNetwork.matches(network), "staticNetwork MUST match network object", "options", options);
 
-                 this.#network = staticNetwork;
 
-             }
 
-         }
 
-         /**
 
-          *  Returns the value associated with the option %%key%%.
 
-          *
 
-          *  Sub-classes can use this to inquire about configuration options.
 
-          */
 
-         _getOption(key) {
 
-             return this.#options[key];
 
-         }
 
-         /**
 
-          *  Gets the [[Network]] this provider has committed to. On each call, the network
 
-          *  is detected, and if it has changed, the call will reject.
 
-          */
 
-         get _network() {
 
-             assert(this.#network, "network is not available yet", "NETWORK_ERROR");
 
-             return this.#network;
 
-         }
 
-         /**
 
-          *  Resolves to the non-normalized value by performing %%req%%.
 
-          *
 
-          *  Sub-classes may override this to modify behavior of actions,
 
-          *  and should generally call ``super._perform`` as a fallback.
 
-          */
 
-         async _perform(req) {
 
-             // Legacy networks do not like the type field being passed along (which
 
-             // is fair), so we delete type if it is 0 and a non-EIP-1559 network
 
-             if (req.method === "call" || req.method === "estimateGas") {
 
-                 let tx = req.transaction;
 
-                 if (tx && tx.type != null && getBigInt(tx.type)) {
 
-                     // If there are no EIP-1559 or newer properties, it might be pre-EIP-1559
 
-                     if (tx.maxFeePerGas == null && tx.maxPriorityFeePerGas == null) {
 
-                         const feeData = await this.getFeeData();
 
-                         if (feeData.maxFeePerGas == null && feeData.maxPriorityFeePerGas == null) {
 
-                             // Network doesn't know about EIP-1559 (and hence type)
 
-                             req = Object.assign({}, req, {
 
-                                 transaction: Object.assign({}, tx, { type: undefined })
 
-                             });
 
-                         }
 
-                     }
 
-                 }
 
-             }
 
-             const request = this.getRpcRequest(req);
 
-             if (request != null) {
 
-                 return await this.send(request.method, request.args);
 
-             }
 
-             return super._perform(req);
 
-         }
 
-         /**
 
-          *  Sub-classes may override this; it detects the *actual* network that
 
-          *  we are **currently** connected to.
 
-          *
 
-          *  Keep in mind that [[send]] may only be used once [[ready]], otherwise the
 
-          *  _send primitive must be used instead.
 
-          */
 
-         async _detectNetwork() {
 
-             const network = this._getOption("staticNetwork");
 
-             if (network) {
 
-                 if (network === true) {
 
-                     if (this.#network) {
 
-                         return this.#network;
 
-                     }
 
-                 }
 
-                 else {
 
-                     return network;
 
-                 }
 
-             }
 
-             if (this.#pendingDetectNetwork) {
 
-                 return await this.#pendingDetectNetwork;
 
-             }
 
-             // If we are ready, use ``send``, which enabled requests to be batched
 
-             if (this.ready) {
 
-                 this.#pendingDetectNetwork = (async () => {
 
-                     try {
 
-                         const result = Network.from(getBigInt(await this.send("eth_chainId", [])));
 
-                         this.#pendingDetectNetwork = null;
 
-                         return result;
 
-                     }
 
-                     catch (error) {
 
-                         this.#pendingDetectNetwork = null;
 
-                         throw error;
 
-                     }
 
-                 })();
 
-                 return await this.#pendingDetectNetwork;
 
-             }
 
-             // We are not ready yet; use the primitive _send
 
-             this.#pendingDetectNetwork = (async () => {
 
-                 const payload = {
 
-                     id: this.#nextId++, method: "eth_chainId", params: [], jsonrpc: "2.0"
 
-                 };
 
-                 this.emit("debug", { action: "sendRpcPayload", payload });
 
-                 let result;
 
-                 try {
 
-                     result = (await this._send(payload))[0];
 
-                     this.#pendingDetectNetwork = null;
 
-                 }
 
-                 catch (error) {
 
-                     this.#pendingDetectNetwork = null;
 
-                     this.emit("debug", { action: "receiveRpcError", error });
 
-                     throw error;
 
-                 }
 
-                 this.emit("debug", { action: "receiveRpcResult", result });
 
-                 if ("result" in result) {
 
-                     return Network.from(getBigInt(result.result));
 
-                 }
 
-                 throw this.getRpcError(payload, result);
 
-             })();
 
-             return await this.#pendingDetectNetwork;
 
-         }
 
-         /**
 
-          *  Sub-classes **MUST** call this. Until [[_start]] has been called, no calls
 
-          *  will be passed to [[_send]] from [[send]]. If it is overridden, then
 
-          *  ``super._start()`` **MUST** be called.
 
-          *
 
-          *  Calling it multiple times is safe and has no effect.
 
-          */
 
-         _start() {
 
-             if (this.#notReady == null || this.#notReady.resolve == null) {
 
-                 return;
 
-             }
 
-             this.#notReady.resolve();
 
-             this.#notReady = null;
 
-             (async () => {
 
-                 // Bootstrap the network
 
-                 while (this.#network == null && !this.destroyed) {
 
-                     try {
 
-                         this.#network = await this._detectNetwork();
 
-                     }
 
-                     catch (error) {
 
-                         if (this.destroyed) {
 
-                             break;
 
-                         }
 
-                         console.log("JsonRpcProvider failed to detect network and cannot start up; retry in 1s (perhaps the URL is wrong or the node is not started)");
 
-                         this.emit("error", makeError("failed to bootstrap network detection", "NETWORK_ERROR", { event: "initial-network-discovery", info: { error } }));
 
-                         await stall$3(1000);
 
-                     }
 
-                 }
 
-                 // Start dispatching requests
 
-                 this.#scheduleDrain();
 
-             })();
 
-         }
 
-         /**
 
-          *  Resolves once the [[_start]] has been called. This can be used in
 
-          *  sub-classes to defer sending data until the connection has been
 
-          *  established.
 
-          */
 
-         async _waitUntilReady() {
 
-             if (this.#notReady == null) {
 
-                 return;
 
-             }
 
-             return await this.#notReady.promise;
 
-         }
 
-         /**
 
-          *  Return a Subscriber that will manage the %%sub%%.
 
-          *
 
-          *  Sub-classes may override this to modify the behavior of
 
-          *  subscription management.
 
-          */
 
-         _getSubscriber(sub) {
 
-             // Pending Filters aren't availble via polling
 
-             if (sub.type === "pending") {
 
-                 return new FilterIdPendingSubscriber(this);
 
-             }
 
-             if (sub.type === "event") {
 
-                 if (this._getOption("polling")) {
 
-                     return new PollingEventSubscriber(this, sub.filter);
 
-                 }
 
-                 return new FilterIdEventSubscriber(this, sub.filter);
 
-             }
 
-             // Orphaned Logs are handled automatically, by the filter, since
 
-             // logs with removed are emitted by it
 
-             if (sub.type === "orphan" && sub.filter.orphan === "drop-log") {
 
-                 return new UnmanagedSubscriber("orphan");
 
-             }
 
-             return super._getSubscriber(sub);
 
-         }
 
-         /**
 
-          *  Returns true only if the [[_start]] has been called.
 
-          */
 
-         get ready() { return this.#notReady == null; }
 
-         /**
 
-          *  Returns %%tx%% as a normalized JSON-RPC transaction request,
 
-          *  which has all values hexlified and any numeric values converted
 
-          *  to Quantity values.
 
-          */
 
-         getRpcTransaction(tx) {
 
-             const result = {};
 
-             // JSON-RPC now requires numeric values to be "quantity" values
 
-             ["chainId", "gasLimit", "gasPrice", "type", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "value"].forEach((key) => {
 
-                 if (tx[key] == null) {
 
-                     return;
 
-                 }
 
-                 let dstKey = key;
 
-                 if (key === "gasLimit") {
 
-                     dstKey = "gas";
 
-                 }
 
-                 result[dstKey] = toQuantity(getBigInt(tx[key], `tx.${key}`));
 
-             });
 
-             // Make sure addresses and data are lowercase
 
-             ["from", "to", "data"].forEach((key) => {
 
-                 if (tx[key] == null) {
 
-                     return;
 
-                 }
 
-                 result[key] = hexlify(tx[key]);
 
-             });
 
-             // Normalize the access list object
 
-             if (tx.accessList) {
 
-                 result["accessList"] = accessListify(tx.accessList);
 
-             }
 
-             if (tx.blobVersionedHashes) {
 
-                 // @TODO: Remove this <any> case once EIP-4844 added to prepared tx
 
-                 result["blobVersionedHashes"] = tx.blobVersionedHashes.map(h => h.toLowerCase());
 
-             }
 
-             // @TODO: blobs should probably also be copied over, optionally
 
-             // accounting for the kzg property to backfill blobVersionedHashes
 
-             // using the commitment. Or should that be left as an exercise to
 
-             // the caller?
 
-             return result;
 
-         }
 
-         /**
 
-          *  Returns the request method and arguments required to perform
 
-          *  %%req%%.
 
-          */
 
-         getRpcRequest(req) {
 
-             switch (req.method) {
 
-                 case "chainId":
 
-                     return { method: "eth_chainId", args: [] };
 
-                 case "getBlockNumber":
 
-                     return { method: "eth_blockNumber", args: [] };
 
-                 case "getGasPrice":
 
-                     return { method: "eth_gasPrice", args: [] };
 
-                 case "getPriorityFee":
 
-                     return { method: "eth_maxPriorityFeePerGas", args: [] };
 
-                 case "getBalance":
 
-                     return {
 
-                         method: "eth_getBalance",
 
-                         args: [getLowerCase(req.address), req.blockTag]
 
-                     };
 
-                 case "getTransactionCount":
 
-                     return {
 
-                         method: "eth_getTransactionCount",
 
-                         args: [getLowerCase(req.address), req.blockTag]
 
-                     };
 
-                 case "getCode":
 
-                     return {
 
-                         method: "eth_getCode",
 
-                         args: [getLowerCase(req.address), req.blockTag]
 
-                     };
 
-                 case "getStorage":
 
-                     return {
 
-                         method: "eth_getStorageAt",
 
-                         args: [
 
-                             getLowerCase(req.address),
 
-                             ("0x" + req.position.toString(16)),
 
-                             req.blockTag
 
-                         ]
 
-                     };
 
-                 case "broadcastTransaction":
 
-                     return {
 
-                         method: "eth_sendRawTransaction",
 
-                         args: [req.signedTransaction]
 
-                     };
 
-                 case "getBlock":
 
-                     if ("blockTag" in req) {
 
-                         return {
 
-                             method: "eth_getBlockByNumber",
 
-                             args: [req.blockTag, !!req.includeTransactions]
 
-                         };
 
-                     }
 
-                     else if ("blockHash" in req) {
 
-                         return {
 
-                             method: "eth_getBlockByHash",
 
-                             args: [req.blockHash, !!req.includeTransactions]
 
-                         };
 
-                     }
 
-                     break;
 
-                 case "getTransaction":
 
-                     return {
 
-                         method: "eth_getTransactionByHash",
 
-                         args: [req.hash]
 
-                     };
 
-                 case "getTransactionReceipt":
 
-                     return {
 
-                         method: "eth_getTransactionReceipt",
 
-                         args: [req.hash]
 
-                     };
 
-                 case "call":
 
-                     return {
 
-                         method: "eth_call",
 
-                         args: [this.getRpcTransaction(req.transaction), req.blockTag]
 
-                     };
 
-                 case "estimateGas": {
 
-                     return {
 
-                         method: "eth_estimateGas",
 
-                         args: [this.getRpcTransaction(req.transaction)]
 
-                     };
 
-                 }
 
-                 case "getLogs":
 
-                     if (req.filter && req.filter.address != null) {
 
-                         if (Array.isArray(req.filter.address)) {
 
-                             req.filter.address = req.filter.address.map(getLowerCase);
 
-                         }
 
-                         else {
 
-                             req.filter.address = getLowerCase(req.filter.address);
 
-                         }
 
-                     }
 
-                     return { method: "eth_getLogs", args: [req.filter] };
 
-             }
 
-             return null;
 
-         }
 
-         /**
 
-          *  Returns an ethers-style Error for the given JSON-RPC error
 
-          *  %%payload%%, coalescing the various strings and error shapes
 
-          *  that different nodes return, coercing them into a machine-readable
 
-          *  standardized error.
 
-          */
 
-         getRpcError(payload, _error) {
 
-             const { method } = payload;
 
-             const { error } = _error;
 
-             if (method === "eth_estimateGas" && error.message) {
 
-                 const msg = error.message;
 
-                 if (!msg.match(/revert/i) && msg.match(/insufficient funds/i)) {
 
-                     return makeError("insufficient funds", "INSUFFICIENT_FUNDS", {
 
-                         transaction: (payload.params[0]),
 
-                         info: { payload, error }
 
-                     });
 
-                 }
 
-             }
 
-             if (method === "eth_call" || method === "eth_estimateGas") {
 
-                 const result = spelunkData(error);
 
-                 const e = AbiCoder.getBuiltinCallException((method === "eth_call") ? "call" : "estimateGas", (payload.params[0]), (result ? result.data : null));
 
-                 e.info = { error, payload };
 
-                 return e;
 
-             }
 
-             // Only estimateGas and call can return arbitrary contract-defined text, so now we
 
-             // we can process text safely.
 
-             const message = JSON.stringify(spelunkMessage(error));
 
-             if (typeof (error.message) === "string" && error.message.match(/user denied|ethers-user-denied/i)) {
 
-                 const actionMap = {
 
-                     eth_sign: "signMessage",
 
-                     personal_sign: "signMessage",
 
-                     eth_signTypedData_v4: "signTypedData",
 
-                     eth_signTransaction: "signTransaction",
 
-                     eth_sendTransaction: "sendTransaction",
 
-                     eth_requestAccounts: "requestAccess",
 
-                     wallet_requestAccounts: "requestAccess",
 
-                 };
 
-                 return makeError(`user rejected action`, "ACTION_REJECTED", {
 
-                     action: (actionMap[method] || "unknown"),
 
-                     reason: "rejected",
 
-                     info: { payload, error }
 
-                 });
 
-             }
 
-             if (method === "eth_sendRawTransaction" || method === "eth_sendTransaction") {
 
-                 const transaction = (payload.params[0]);
 
-                 if (message.match(/insufficient funds|base fee exceeds gas limit/i)) {
 
-                     return makeError("insufficient funds for intrinsic transaction cost", "INSUFFICIENT_FUNDS", {
 
-                         transaction, info: { error }
 
-                     });
 
-                 }
 
-                 if (message.match(/nonce/i) && message.match(/too low/i)) {
 
-                     return makeError("nonce has already been used", "NONCE_EXPIRED", { transaction, info: { error } });
 
-                 }
 
-                 // "replacement transaction underpriced"
 
-                 if (message.match(/replacement transaction/i) && message.match(/underpriced/i)) {
 
-                     return makeError("replacement fee too low", "REPLACEMENT_UNDERPRICED", { transaction, info: { error } });
 
-                 }
 
-                 if (message.match(/only replay-protected/i)) {
 
-                     return makeError("legacy pre-eip-155 transactions not supported", "UNSUPPORTED_OPERATION", {
 
-                         operation: method, info: { transaction, info: { error } }
 
-                     });
 
-                 }
 
-             }
 
-             let unsupported = !!message.match(/the method .* does not exist/i);
 
-             if (!unsupported) {
 
-                 if (error && error.details && error.details.startsWith("Unauthorized method:")) {
 
-                     unsupported = true;
 
-                 }
 
-             }
 
-             if (unsupported) {
 
-                 return makeError("unsupported operation", "UNSUPPORTED_OPERATION", {
 
-                     operation: payload.method, info: { error, payload }
 
-                 });
 
-             }
 
-             return makeError("could not coalesce error", "UNKNOWN_ERROR", { error, payload });
 
-         }
 
-         /**
 
-          *  Requests the %%method%% with %%params%% via the JSON-RPC protocol
 
-          *  over the underlying channel. This can be used to call methods
 
-          *  on the backend that do not have a high-level API within the Provider
 
-          *  API.
 
-          *
 
-          *  This method queues requests according to the batch constraints
 
-          *  in the options, assigns the request a unique ID.
 
-          *
 
-          *  **Do NOT override** this method in sub-classes; instead
 
-          *  override [[_send]] or force the options values in the
 
-          *  call to the constructor to modify this method's behavior.
 
-          */
 
-         send(method, params) {
 
-             // @TODO: cache chainId?? purge on switch_networks
 
-             // We have been destroyed; no operations are supported anymore
 
-             if (this.destroyed) {
 
-                 return Promise.reject(makeError("provider destroyed; cancelled request", "UNSUPPORTED_OPERATION", { operation: method }));
 
-             }
 
-             const id = this.#nextId++;
 
-             const promise = new Promise((resolve, reject) => {
 
-                 this.#payloads.push({
 
-                     resolve, reject,
 
-                     payload: { method, params, id, jsonrpc: "2.0" }
 
-                 });
 
-             });
 
-             // If there is not a pending drainTimer, set one
 
-             this.#scheduleDrain();
 
-             return promise;
 
-         }
 
-         /**
 
-          *  Resolves to the [[Signer]] account for  %%address%% managed by
 
-          *  the client.
 
-          *
 
-          *  If the %%address%% is a number, it is used as an index in the
 
-          *  the accounts from [[listAccounts]].
 
-          *
 
-          *  This can only be used on clients which manage accounts (such as
 
-          *  Geth with imported account or MetaMask).
 
-          *
 
-          *  Throws if the account doesn't exist.
 
-          */
 
-         async getSigner(address) {
 
-             if (address == null) {
 
-                 address = 0;
 
-             }
 
-             const accountsPromise = this.send("eth_accounts", []);
 
-             // Account index
 
-             if (typeof (address) === "number") {
 
-                 const accounts = (await accountsPromise);
 
-                 if (address >= accounts.length) {
 
-                     throw new Error("no such account");
 
-                 }
 
-                 return new JsonRpcSigner(this, accounts[address]);
 
-             }
 
-             const { accounts } = await resolveProperties({
 
-                 network: this.getNetwork(),
 
-                 accounts: accountsPromise
 
-             });
 
-             // Account address
 
-             address = getAddress(address);
 
-             for (const account of accounts) {
 
-                 if (getAddress(account) === address) {
 
-                     return new JsonRpcSigner(this, address);
 
-                 }
 
-             }
 
-             throw new Error("invalid account");
 
-         }
 
-         async listAccounts() {
 
-             const accounts = await this.send("eth_accounts", []);
 
-             return accounts.map((a) => new JsonRpcSigner(this, a));
 
-         }
 
-         destroy() {
 
-             // Stop processing requests
 
-             if (this.#drainTimer) {
 
-                 clearTimeout(this.#drainTimer);
 
-                 this.#drainTimer = null;
 
-             }
 
-             // Cancel all pending requests
 
-             for (const { payload, reject } of this.#payloads) {
 
-                 reject(makeError("provider destroyed; cancelled request", "UNSUPPORTED_OPERATION", { operation: payload.method }));
 
-             }
 
-             this.#payloads = [];
 
-             // Parent clean-up
 
-             super.destroy();
 
-         }
 
-     }
 
-     // @TODO: remove this in v7, it is not exported because this functionality
 
-     // is exposed in the JsonRpcApiProvider by setting polling to true. It should
 
-     // be safe to remove regardless, because it isn't reachable, but just in case.
 
-     /**
 
-      *  @_ignore:
 
-      */
 
-     class JsonRpcApiPollingProvider extends JsonRpcApiProvider {
 
-         #pollingInterval;
 
-         constructor(network, options) {
 
-             super(network, options);
 
-             let pollingInterval = this._getOption("pollingInterval");
 
-             if (pollingInterval == null) {
 
-                 pollingInterval = defaultOptions.pollingInterval;
 
-             }
 
-             this.#pollingInterval = pollingInterval;
 
-         }
 
-         _getSubscriber(sub) {
 
-             const subscriber = super._getSubscriber(sub);
 
-             if (isPollable(subscriber)) {
 
-                 subscriber.pollingInterval = this.#pollingInterval;
 
-             }
 
-             return subscriber;
 
-         }
 
-         /**
 
-          *  The polling interval (default: 4000 ms)
 
-          */
 
-         get pollingInterval() { return this.#pollingInterval; }
 
-         set pollingInterval(value) {
 
-             if (!Number.isInteger(value) || value < 0) {
 
-                 throw new Error("invalid interval");
 
-             }
 
-             this.#pollingInterval = value;
 
-             this._forEachSubscriber((sub) => {
 
-                 if (isPollable(sub)) {
 
-                     sub.pollingInterval = this.#pollingInterval;
 
-                 }
 
-             });
 
-         }
 
-     }
 
-     /**
 
-      *  The JsonRpcProvider is one of the most common Providers,
 
-      *  which performs all operations over HTTP (or HTTPS) requests.
 
-      *
 
-      *  Events are processed by polling the backend for the current block
 
-      *  number; when it advances, all block-base events are then checked
 
-      *  for updates.
 
-      */
 
-     class JsonRpcProvider extends JsonRpcApiPollingProvider {
 
-         #connect;
 
-         constructor(url, network, options) {
 
-             if (url == null) {
 
-                 url = "http:/\/localhost:8545";
 
-             }
 
-             super(network, options);
 
-             if (typeof (url) === "string") {
 
-                 this.#connect = new FetchRequest(url);
 
-             }
 
-             else {
 
-                 this.#connect = url.clone();
 
-             }
 
-         }
 
-         _getConnection() {
 
-             return this.#connect.clone();
 
-         }
 
-         async send(method, params) {
 
-             // All requests are over HTTP, so we can just start handling requests
 
-             // We do this here rather than the constructor so that we don't send any
 
-             // requests to the network (i.e. eth_chainId) until we absolutely have to.
 
-             await this._start();
 
-             return await super.send(method, params);
 
-         }
 
-         async _send(payload) {
 
-             // Configure a POST connection for the requested method
 
-             const request = this._getConnection();
 
-             request.body = JSON.stringify(payload);
 
-             request.setHeader("content-type", "application/json");
 
-             const response = await request.send();
 
-             response.assertOk();
 
-             let resp = response.bodyJson;
 
-             if (!Array.isArray(resp)) {
 
-                 resp = [resp];
 
-             }
 
-             return resp;
 
-         }
 
-     }
 
-     function spelunkData(value) {
 
-         if (value == null) {
 
-             return null;
 
-         }
 
-         // These *are* the droids we're looking for.
 
-         if (typeof (value.message) === "string" && value.message.match(/revert/i) && isHexString(value.data)) {
 
-             return { message: value.message, data: value.data };
 
-         }
 
-         // Spelunk further...
 
-         if (typeof (value) === "object") {
 
-             for (const key in value) {
 
-                 const result = spelunkData(value[key]);
 
-                 if (result) {
 
-                     return result;
 
-                 }
 
-             }
 
-             return null;
 
-         }
 
-         // Might be a JSON string we can further descend...
 
-         if (typeof (value) === "string") {
 
-             try {
 
-                 return spelunkData(JSON.parse(value));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         return null;
 
-     }
 
-     function _spelunkMessage(value, result) {
 
-         if (value == null) {
 
-             return;
 
-         }
 
-         // These *are* the droids we're looking for.
 
-         if (typeof (value.message) === "string") {
 
-             result.push(value.message);
 
-         }
 
-         // Spelunk further...
 
-         if (typeof (value) === "object") {
 
-             for (const key in value) {
 
-                 _spelunkMessage(value[key], result);
 
-             }
 
-         }
 
-         // Might be a JSON string we can further descend...
 
-         if (typeof (value) === "string") {
 
-             try {
 
-                 return _spelunkMessage(JSON.parse(value), result);
 
-             }
 
-             catch (error) { }
 
-         }
 
-     }
 
-     function spelunkMessage(value) {
 
-         const result = [];
 
-         _spelunkMessage(value, result);
 
-         return result;
 
-     }
 
-     /**
 
-      *  [[link-ankr]] provides a third-party service for connecting to
 
-      *  various blockchains over JSON-RPC.
 
-      *
 
-      *  **Supported Networks**
 
-      *
 
-      *  - Ethereum Mainnet (``mainnet``)
 
-      *  - Goerli Testnet (``goerli``)
 
-      *  - Sepolia Testnet (``sepolia``)
 
-      *  - Arbitrum (``arbitrum``)
 
-      *  - Base (``base``)
 
-      *  - Base Goerlia Testnet (``base-goerli``)
 
-      *  - Base Sepolia Testnet (``base-sepolia``)
 
-      *  - BNB (``bnb``)
 
-      *  - BNB Testnet (``bnbt``)
 
-      *  - Optimism (``optimism``)
 
-      *  - Optimism Goerli Testnet (``optimism-goerli``)
 
-      *  - Optimism Sepolia Testnet (``optimism-sepolia``)
 
-      *  - Polygon (``matic``)
 
-      *  - Polygon Mumbai Testnet (``matic-mumbai``)
 
-      *
 
-      *  @_subsection: api/providers/thirdparty:Ankr  [providers-ankr]
 
-      */
 
-     const defaultApiKey$1 = "9f7d929b018cdffb338517efa06f58359e86ff1ffd350bc889738523659e7972";
 
-     function getHost$5(name) {
 
-         switch (name) {
 
-             case "mainnet":
 
-                 return "rpc.ankr.com/eth";
 
-             case "goerli":
 
-                 return "rpc.ankr.com/eth_goerli";
 
-             case "sepolia":
 
-                 return "rpc.ankr.com/eth_sepolia";
 
-             case "arbitrum":
 
-                 return "rpc.ankr.com/arbitrum";
 
-             case "base":
 
-                 return "rpc.ankr.com/base";
 
-             case "base-goerli":
 
-                 return "rpc.ankr.com/base_goerli";
 
-             case "base-sepolia":
 
-                 return "rpc.ankr.com/base_sepolia";
 
-             case "bnb":
 
-                 return "rpc.ankr.com/bsc";
 
-             case "bnbt":
 
-                 return "rpc.ankr.com/bsc_testnet_chapel";
 
-             case "matic":
 
-                 return "rpc.ankr.com/polygon";
 
-             case "matic-mumbai":
 
-                 return "rpc.ankr.com/polygon_mumbai";
 
-             case "optimism":
 
-                 return "rpc.ankr.com/optimism";
 
-             case "optimism-goerli":
 
-                 return "rpc.ankr.com/optimism_testnet";
 
-             case "optimism-sepolia":
 
-                 return "rpc.ankr.com/optimism_sepolia";
 
-         }
 
-         assertArgument(false, "unsupported network", "network", name);
 
-     }
 
-     /**
 
-      *  The **AnkrProvider** connects to the [[link-ankr]]
 
-      *  JSON-RPC end-points.
 
-      *
 
-      *  By default, a highly-throttled API key is used, which is
 
-      *  appropriate for quick prototypes and simple scripts. To
 
-      *  gain access to an increased rate-limit, it is highly
 
-      *  recommended to [sign up here](link-ankr-signup).
 
-      */
 
-     class AnkrProvider extends JsonRpcProvider {
 
-         /**
 
-          *  The API key for the Ankr connection.
 
-          */
 
-         apiKey;
 
-         /**
 
-          *  Create a new **AnkrProvider**.
 
-          *
 
-          *  By default connecting to ``mainnet`` with a highly throttled
 
-          *  API key.
 
-          */
 
-         constructor(_network, apiKey) {
 
-             if (_network == null) {
 
-                 _network = "mainnet";
 
-             }
 
-             const network = Network.from(_network);
 
-             if (apiKey == null) {
 
-                 apiKey = defaultApiKey$1;
 
-             }
 
-             // Ankr does not support filterId, so we force polling
 
-             const options = { polling: true, staticNetwork: network };
 
-             const request = AnkrProvider.getRequest(network, apiKey);
 
-             super(request, network, options);
 
-             defineProperties(this, { apiKey });
 
-         }
 
-         _getProvider(chainId) {
 
-             try {
 
-                 return new AnkrProvider(chainId, this.apiKey);
 
-             }
 
-             catch (error) { }
 
-             return super._getProvider(chainId);
 
-         }
 
-         /**
 
-          *  Returns a prepared request for connecting to %%network%% with
 
-          *  %%apiKey%%.
 
-          */
 
-         static getRequest(network, apiKey) {
 
-             if (apiKey == null) {
 
-                 apiKey = defaultApiKey$1;
 
-             }
 
-             const request = new FetchRequest(`https:/\/${getHost$5(network.name)}/${apiKey}`);
 
-             request.allowGzip = true;
 
-             if (apiKey === defaultApiKey$1) {
 
-                 request.retryFunc = async (request, response, attempt) => {
 
-                     showThrottleMessage("AnkrProvider");
 
-                     return true;
 
-                 };
 
-             }
 
-             return request;
 
-         }
 
-         getRpcError(payload, error) {
 
-             if (payload.method === "eth_sendRawTransaction") {
 
-                 if (error && error.error && error.error.message === "INTERNAL_ERROR: could not replace existing tx") {
 
-                     error.error.message = "replacement transaction underpriced";
 
-                 }
 
-             }
 
-             return super.getRpcError(payload, error);
 
-         }
 
-         isCommunityResource() {
 
-             return (this.apiKey === defaultApiKey$1);
 
-         }
 
-     }
 
-     /**
 
-      *  [[link-alchemy]] provides a third-party service for connecting to
 
-      *  various blockchains over JSON-RPC.
 
-      *
 
-      *  **Supported Networks**
 
-      *
 
-      *  - Ethereum Mainnet (``mainnet``)
 
-      *  - Goerli Testnet (``goerli``)
 
-      *  - Sepolia Testnet (``sepolia``)
 
-      *  - Arbitrum (``arbitrum``)
 
-      *  - Arbitrum Goerli Testnet (``arbitrum-goerli``)
 
-      *  - Arbitrum Sepolia Testnet (``arbitrum-sepolia``)
 
-      *  - Base (``base``)
 
-      *  - Base Goerlia Testnet (``base-goerli``)
 
-      *  - Base Sepolia Testnet (``base-sepolia``)
 
-      *  - Optimism (``optimism``)
 
-      *  - Optimism Goerli Testnet (``optimism-goerli``)
 
-      *  - Optimism Sepolia Testnet (``optimism-sepolia``)
 
-      *  - Polygon (``matic``)
 
-      *  - Polygon Amoy Testnet (``matic-amoy``)
 
-      *  - Polygon Mumbai Testnet (``matic-mumbai``)
 
-      *
 
-      *  @_subsection: api/providers/thirdparty:Alchemy  [providers-alchemy]
 
-      */
 
-     const defaultApiKey = "_gg7wSSi0KMBsdKnGVfHDueq6xMB9EkC";
 
-     function getHost$4(name) {
 
-         switch (name) {
 
-             case "mainnet":
 
-                 return "eth-mainnet.alchemyapi.io";
 
-             case "goerli":
 
-                 return "eth-goerli.g.alchemy.com";
 
-             case "sepolia":
 
-                 return "eth-sepolia.g.alchemy.com";
 
-             case "arbitrum":
 
-                 return "arb-mainnet.g.alchemy.com";
 
-             case "arbitrum-goerli":
 
-                 return "arb-goerli.g.alchemy.com";
 
-             case "arbitrum-sepolia":
 
-                 return "arb-sepolia.g.alchemy.com";
 
-             case "base":
 
-                 return "base-mainnet.g.alchemy.com";
 
-             case "base-goerli":
 
-                 return "base-goerli.g.alchemy.com";
 
-             case "base-sepolia":
 
-                 return "base-sepolia.g.alchemy.com";
 
-             case "matic":
 
-                 return "polygon-mainnet.g.alchemy.com";
 
-             case "matic-amoy":
 
-                 return "polygon-amoy.g.alchemy.com";
 
-             case "matic-mumbai":
 
-                 return "polygon-mumbai.g.alchemy.com";
 
-             case "optimism":
 
-                 return "opt-mainnet.g.alchemy.com";
 
-             case "optimism-goerli":
 
-                 return "opt-goerli.g.alchemy.com";
 
-             case "optimism-sepolia":
 
-                 return "opt-sepolia.g.alchemy.com";
 
-         }
 
-         assertArgument(false, "unsupported network", "network", name);
 
-     }
 
-     /**
 
-      *  The **AlchemyProvider** connects to the [[link-alchemy]]
 
-      *  JSON-RPC end-points.
 
-      *
 
-      *  By default, a highly-throttled API key is used, which is
 
-      *  appropriate for quick prototypes and simple scripts. To
 
-      *  gain access to an increased rate-limit, it is highly
 
-      *  recommended to [sign up here](link-alchemy-signup).
 
-      *
 
-      *  @_docloc: api/providers/thirdparty
 
-      */
 
-     class AlchemyProvider extends JsonRpcProvider {
 
-         apiKey;
 
-         constructor(_network, apiKey) {
 
-             if (_network == null) {
 
-                 _network = "mainnet";
 
-             }
 
-             const network = Network.from(_network);
 
-             if (apiKey == null) {
 
-                 apiKey = defaultApiKey;
 
-             }
 
-             const request = AlchemyProvider.getRequest(network, apiKey);
 
-             super(request, network, { staticNetwork: network });
 
-             defineProperties(this, { apiKey });
 
-         }
 
-         _getProvider(chainId) {
 
-             try {
 
-                 return new AlchemyProvider(chainId, this.apiKey);
 
-             }
 
-             catch (error) { }
 
-             return super._getProvider(chainId);
 
-         }
 
-         async _perform(req) {
 
-             // https://docs.alchemy.com/reference/trace-transaction
 
-             if (req.method === "getTransactionResult") {
 
-                 const { trace, tx } = await resolveProperties({
 
-                     trace: this.send("trace_transaction", [req.hash]),
 
-                     tx: this.getTransaction(req.hash)
 
-                 });
 
-                 if (trace == null || tx == null) {
 
-                     return null;
 
-                 }
 
-                 let data;
 
-                 let error = false;
 
-                 try {
 
-                     data = trace[0].result.output;
 
-                     error = (trace[0].error === "Reverted");
 
-                 }
 
-                 catch (error) { }
 
-                 if (data) {
 
-                     assert(!error, "an error occurred during transaction executions", "CALL_EXCEPTION", {
 
-                         action: "getTransactionResult",
 
-                         data,
 
-                         reason: null,
 
-                         transaction: tx,
 
-                         invocation: null,
 
-                         revert: null // @TODO
 
-                     });
 
-                     return data;
 
-                 }
 
-                 assert(false, "could not parse trace result", "BAD_DATA", { value: trace });
 
-             }
 
-             return await super._perform(req);
 
-         }
 
-         isCommunityResource() {
 
-             return (this.apiKey === defaultApiKey);
 
-         }
 
-         static getRequest(network, apiKey) {
 
-             if (apiKey == null) {
 
-                 apiKey = defaultApiKey;
 
-             }
 
-             const request = new FetchRequest(`https:/\/${getHost$4(network.name)}/v2/${apiKey}`);
 
-             request.allowGzip = true;
 
-             if (apiKey === defaultApiKey) {
 
-                 request.retryFunc = async (request, response, attempt) => {
 
-                     showThrottleMessage("alchemy");
 
-                     return true;
 
-                 };
 
-             }
 
-             return request;
 
-         }
 
-     }
 
-     /**
 
-      *  [[link-chainstack]] provides a third-party service for connecting to
 
-      *  various blockchains over JSON-RPC.
 
-      *
 
-      *  **Supported Networks**
 
-      *
 
-      *  - Ethereum Mainnet (``mainnet``)
 
-      *  - Arbitrum (``arbitrum``)
 
-      *  - BNB Smart Chain Mainnet (``bnb``)
 
-      *  - Polygon (``matic``)
 
-      *
 
-      *  @_subsection: api/providers/thirdparty:Chainstack  [providers-chainstack]
 
-      */
 
-     function getApiKey(name) {
 
-         switch (name) {
 
-             case "mainnet": return "39f1d67cedf8b7831010a665328c9197";
 
-             case "arbitrum": return "0550c209db33c3abf4cc927e1e18cea1";
 
-             case "bnb": return "98b5a77e531614387366f6fc5da097f8";
 
-             case "matic": return "cd9d4d70377471aa7c142ec4a4205249";
 
-         }
 
-         assertArgument(false, "unsupported network", "network", name);
 
-     }
 
-     function getHost$3(name) {
 
-         switch (name) {
 
-             case "mainnet":
 
-                 return "ethereum-mainnet.core.chainstack.com";
 
-             case "arbitrum":
 
-                 return "arbitrum-mainnet.core.chainstack.com";
 
-             case "bnb":
 
-                 return "bsc-mainnet.core.chainstack.com";
 
-             case "matic":
 
-                 return "polygon-mainnet.core.chainstack.com";
 
-         }
 
-         assertArgument(false, "unsupported network", "network", name);
 
-     }
 
-     /**
 
-      *  The **ChainstackProvider** connects to the [[link-chainstack]]
 
-      *  JSON-RPC end-points.
 
-      *
 
-      *  By default, a highly-throttled API key is used, which is
 
-      *  appropriate for quick prototypes and simple scripts. To
 
-      *  gain access to an increased rate-limit, it is highly
 
-      *  recommended to [sign up here](link-chainstack).
 
-      */
 
-     class ChainstackProvider extends JsonRpcProvider {
 
-         /**
 
-          *  The API key for the Chainstack connection.
 
-          */
 
-         apiKey;
 
-         /**
 
-          *  Creates a new **ChainstackProvider**.
 
-          */
 
-         constructor(_network, apiKey) {
 
-             if (_network == null) {
 
-                 _network = "mainnet";
 
-             }
 
-             const network = Network.from(_network);
 
-             if (apiKey == null) {
 
-                 apiKey = getApiKey(network.name);
 
-             }
 
-             const request = ChainstackProvider.getRequest(network, apiKey);
 
-             super(request, network, { staticNetwork: network });
 
-             defineProperties(this, { apiKey });
 
-         }
 
-         _getProvider(chainId) {
 
-             try {
 
-                 return new ChainstackProvider(chainId, this.apiKey);
 
-             }
 
-             catch (error) { }
 
-             return super._getProvider(chainId);
 
-         }
 
-         isCommunityResource() {
 
-             return (this.apiKey === getApiKey(this._network.name));
 
-         }
 
-         /**
 
-          *  Returns a prepared request for connecting to %%network%%
 
-          *  with %%apiKey%% and %%projectSecret%%.
 
-          */
 
-         static getRequest(network, apiKey) {
 
-             if (apiKey == null) {
 
-                 apiKey = getApiKey(network.name);
 
-             }
 
-             const request = new FetchRequest(`https:/\/${getHost$3(network.name)}/${apiKey}`);
 
-             request.allowGzip = true;
 
-             if (apiKey === getApiKey(network.name)) {
 
-                 request.retryFunc = async (request, response, attempt) => {
 
-                     showThrottleMessage("ChainstackProvider");
 
-                     return true;
 
-                 };
 
-             }
 
-             return request;
 
-         }
 
-     }
 
-     /**
 
-      *  About Cloudflare
 
-      *
 
-      *  @_subsection: api/providers/thirdparty:Cloudflare  [providers-cloudflare]
 
-      */
 
-     /**
 
-      *  About Cloudflare...
 
-      */
 
-     class CloudflareProvider extends JsonRpcProvider {
 
-         constructor(_network) {
 
-             if (_network == null) {
 
-                 _network = "mainnet";
 
-             }
 
-             const network = Network.from(_network);
 
-             assertArgument(network.name === "mainnet", "unsupported network", "network", _network);
 
-             super("https:/\/cloudflare-eth.com/", network, { staticNetwork: network });
 
-         }
 
-     }
 
-     /**
 
-      *  [[link-etherscan]] provides a third-party service for connecting to
 
-      *  various blockchains over a combination of JSON-RPC and custom API
 
-      *  endpoints.
 
-      *
 
-      *  **Supported Networks**
 
-      *
 
-      *  - Ethereum Mainnet (``mainnet``)
 
-      *  - Goerli Testnet (``goerli``)
 
-      *  - Sepolia Testnet (``sepolia``)
 
-      *  - Holesky Testnet (``holesky``)
 
-      *  - Arbitrum (``arbitrum``)
 
-      *  - Arbitrum Goerli Testnet (``arbitrum-goerli``)
 
-      *  - Base (``base``)
 
-      *  - Base Sepolia Testnet (``base-sepolia``)
 
-      *  - BNB Smart Chain Mainnet (``bnb``)
 
-      *  - BNB Smart Chain Testnet (``bnbt``)
 
-      *  - Optimism (``optimism``)
 
-      *  - Optimism Goerli Testnet (``optimism-goerli``)
 
-      *  - Polygon (``matic``)
 
-      *  - Polygon Mumbai Testnet (``matic-mumbai``)
 
-      *  - Polygon Amoy Testnet (``matic-amoy``)
 
-      *
 
-      *  @_subsection api/providers/thirdparty:Etherscan  [providers-etherscan]
 
-      */
 
-     const THROTTLE = 2000;
 
-     function isPromise(value) {
 
-         return (value && typeof (value.then) === "function");
 
-     }
 
-     const EtherscanPluginId = "org.ethers.plugins.provider.Etherscan";
 
-     /**
 
-      *  A Network can include an **EtherscanPlugin** to provide
 
-      *  a custom base URL.
 
-      *
 
-      *  @_docloc: api/providers/thirdparty:Etherscan
 
-      */
 
-     class EtherscanPlugin extends NetworkPlugin {
 
-         /**
 
-          *  The Etherscan API base URL.
 
-          */
 
-         baseUrl;
 
-         /**
 
-          *  Creates a new **EtherscanProvider** which will use
 
-          *  %%baseUrl%%.
 
-          */
 
-         constructor(baseUrl) {
 
-             super(EtherscanPluginId);
 
-             defineProperties(this, { baseUrl });
 
-         }
 
-         clone() {
 
-             return new EtherscanPlugin(this.baseUrl);
 
-         }
 
-     }
 
-     const skipKeys = ["enableCcipRead"];
 
-     let nextId = 1;
 
-     /**
 
-      *  The **EtherscanBaseProvider** is the super-class of
 
-      *  [[EtherscanProvider]], which should generally be used instead.
 
-      *
 
-      *  Since the **EtherscanProvider** includes additional code for
 
-      *  [[Contract]] access, in //rare cases// that contracts are not
 
-      *  used, this class can reduce code size.
 
-      *
 
-      *  @_docloc: api/providers/thirdparty:Etherscan
 
-      */
 
-     class EtherscanProvider extends AbstractProvider {
 
-         /**
 
-          *  The connected network.
 
-          */
 
-         network;
 
-         /**
 
-          *  The API key or null if using the community provided bandwidth.
 
-          */
 
-         apiKey;
 
-         #plugin;
 
-         /**
 
-          *  Creates a new **EtherscanBaseProvider**.
 
-          */
 
-         constructor(_network, _apiKey) {
 
-             const apiKey = (_apiKey != null) ? _apiKey : null;
 
-             super();
 
-             const network = Network.from(_network);
 
-             this.#plugin = network.getPlugin(EtherscanPluginId);
 
-             defineProperties(this, { apiKey, network });
 
-             // Test that the network is supported by Etherscan
 
-             this.getBaseUrl();
 
-         }
 
-         /**
 
-          *  Returns the base URL.
 
-          *
 
-          *  If an [[EtherscanPlugin]] is configured on the
 
-          *  [[EtherscanBaseProvider_network]], returns the plugin's
 
-          *  baseUrl.
 
-          */
 
-         getBaseUrl() {
 
-             if (this.#plugin) {
 
-                 return this.#plugin.baseUrl;
 
-             }
 
-             switch (this.network.name) {
 
-                 case "mainnet":
 
-                     return "https:/\/api.etherscan.io";
 
-                 case "goerli":
 
-                     return "https:/\/api-goerli.etherscan.io";
 
-                 case "sepolia":
 
-                     return "https:/\/api-sepolia.etherscan.io";
 
-                 case "holesky":
 
-                     return "https:/\/api-holesky.etherscan.io";
 
-                 case "arbitrum":
 
-                     return "https:/\/api.arbiscan.io";
 
-                 case "arbitrum-goerli":
 
-                     return "https:/\/api-goerli.arbiscan.io";
 
-                 case "base":
 
-                     return "https:/\/api.basescan.org";
 
-                 case "base-sepolia":
 
-                     return "https:/\/api-sepolia.basescan.org";
 
-                 case "bnb":
 
-                     return "https:/\/api.bscscan.com";
 
-                 case "bnbt":
 
-                     return "https:/\/api-testnet.bscscan.com";
 
-                 case "matic":
 
-                     return "https:/\/api.polygonscan.com";
 
-                 case "matic-amoy":
 
-                     return "https:/\/api-amoy.polygonscan.com";
 
-                 case "matic-mumbai":
 
-                     return "https:/\/api-testnet.polygonscan.com";
 
-                 case "optimism":
 
-                     return "https:/\/api-optimistic.etherscan.io";
 
-                 case "optimism-goerli":
 
-                     return "https:/\/api-goerli-optimistic.etherscan.io";
 
-             }
 
-             assertArgument(false, "unsupported network", "network", this.network);
 
-         }
 
-         /**
 
-          *  Returns the URL for the %%module%% and %%params%%.
 
-          */
 
-         getUrl(module, params) {
 
-             const query = Object.keys(params).reduce((accum, key) => {
 
-                 const value = params[key];
 
-                 if (value != null) {
 
-                     accum += `&${key}=${value}`;
 
-                 }
 
-                 return accum;
 
-             }, "");
 
-             const apiKey = ((this.apiKey) ? `&apikey=${this.apiKey}` : "");
 
-             return `${this.getBaseUrl()}/api?module=${module}${query}${apiKey}`;
 
-         }
 
-         /**
 
-          *  Returns the URL for using POST requests.
 
-          */
 
-         getPostUrl() {
 
-             return `${this.getBaseUrl()}/api`;
 
-         }
 
-         /**
 
-          *  Returns the parameters for using POST requests.
 
-          */
 
-         getPostData(module, params) {
 
-             params.module = module;
 
-             params.apikey = this.apiKey;
 
-             return params;
 
-         }
 
-         async detectNetwork() {
 
-             return this.network;
 
-         }
 
-         /**
 
-          *  Resolves to the result of calling %%module%% with %%params%%.
 
-          *
 
-          *  If %%post%%, the request is made as a POST request.
 
-          */
 
-         async fetch(module, params, post) {
 
-             const id = nextId++;
 
-             const url = (post ? this.getPostUrl() : this.getUrl(module, params));
 
-             const payload = (post ? this.getPostData(module, params) : null);
 
-             this.emit("debug", { action: "sendRequest", id, url, payload: payload });
 
-             const request = new FetchRequest(url);
 
-             request.setThrottleParams({ slotInterval: 1000 });
 
-             request.retryFunc = (req, resp, attempt) => {
 
-                 if (this.isCommunityResource()) {
 
-                     showThrottleMessage("Etherscan");
 
-                 }
 
-                 return Promise.resolve(true);
 
-             };
 
-             request.processFunc = async (request, response) => {
 
-                 const result = response.hasBody() ? JSON.parse(toUtf8String(response.body)) : {};
 
-                 const throttle = ((typeof (result.result) === "string") ? result.result : "").toLowerCase().indexOf("rate limit") >= 0;
 
-                 if (module === "proxy") {
 
-                     // This JSON response indicates we are being throttled
 
-                     if (result && result.status == 0 && result.message == "NOTOK" && throttle) {
 
-                         this.emit("debug", { action: "receiveError", id, reason: "proxy-NOTOK", error: result });
 
-                         response.throwThrottleError(result.result, THROTTLE);
 
-                     }
 
-                 }
 
-                 else {
 
-                     if (throttle) {
 
-                         this.emit("debug", { action: "receiveError", id, reason: "null result", error: result.result });
 
-                         response.throwThrottleError(result.result, THROTTLE);
 
-                     }
 
-                 }
 
-                 return response;
 
-             };
 
-             if (payload) {
 
-                 request.setHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8");
 
-                 request.body = Object.keys(payload).map((k) => `${k}=${payload[k]}`).join("&");
 
-             }
 
-             const response = await request.send();
 
-             try {
 
-                 response.assertOk();
 
-             }
 
-             catch (error) {
 
-                 this.emit("debug", { action: "receiveError", id, error, reason: "assertOk" });
 
-                 assert(false, "response error", "SERVER_ERROR", { request, response });
 
-             }
 
-             if (!response.hasBody()) {
 
-                 this.emit("debug", { action: "receiveError", id, error: "missing body", reason: "null body" });
 
-                 assert(false, "missing response", "SERVER_ERROR", { request, response });
 
-             }
 
-             const result = JSON.parse(toUtf8String(response.body));
 
-             if (module === "proxy") {
 
-                 if (result.jsonrpc != "2.0") {
 
-                     this.emit("debug", { action: "receiveError", id, result, reason: "invalid JSON-RPC" });
 
-                     assert(false, "invalid JSON-RPC response (missing jsonrpc='2.0')", "SERVER_ERROR", { request, response, info: { result } });
 
-                 }
 
-                 if (result.error) {
 
-                     this.emit("debug", { action: "receiveError", id, result, reason: "JSON-RPC error" });
 
-                     assert(false, "error response", "SERVER_ERROR", { request, response, info: { result } });
 
-                 }
 
-                 this.emit("debug", { action: "receiveRequest", id, result });
 
-                 return result.result;
 
-             }
 
-             else {
 
-                 // getLogs, getHistory have weird success responses
 
-                 if (result.status == 0 && (result.message === "No records found" || result.message === "No transactions found")) {
 
-                     this.emit("debug", { action: "receiveRequest", id, result });
 
-                     return result.result;
 
-                 }
 
-                 if (result.status != 1 || (typeof (result.message) === "string" && !result.message.match(/^OK/))) {
 
-                     this.emit("debug", { action: "receiveError", id, result });
 
-                     assert(false, "error response", "SERVER_ERROR", { request, response, info: { result } });
 
-                 }
 
-                 this.emit("debug", { action: "receiveRequest", id, result });
 
-                 return result.result;
 
-             }
 
-         }
 
-         /**
 
-          *  Returns %%transaction%% normalized for the Etherscan API.
 
-          */
 
-         _getTransactionPostData(transaction) {
 
-             const result = {};
 
-             for (let key in transaction) {
 
-                 if (skipKeys.indexOf(key) >= 0) {
 
-                     continue;
 
-                 }
 
-                 if (transaction[key] == null) {
 
-                     continue;
 
-                 }
 
-                 let value = transaction[key];
 
-                 if (key === "type" && value === 0) {
 
-                     continue;
 
-                 }
 
-                 if (key === "blockTag" && value === "latest") {
 
-                     continue;
 
-                 }
 
-                 // Quantity-types require no leading zero, unless 0
 
-                 if ({ type: true, gasLimit: true, gasPrice: true, maxFeePerGs: true, maxPriorityFeePerGas: true, nonce: true, value: true }[key]) {
 
-                     value = toQuantity(value);
 
-                 }
 
-                 else if (key === "accessList") {
 
-                     value = "[" + accessListify(value).map((set) => {
 
-                         return `{address:"${set.address}",storageKeys:["${set.storageKeys.join('","')}"]}`;
 
-                     }).join(",") + "]";
 
-                 }
 
-                 else if (key === "blobVersionedHashes") {
 
-                     if (value.length === 0) {
 
-                         continue;
 
-                     }
 
-                     // @TODO: update this once the API supports blobs
 
-                     assert(false, "Etherscan API does not support blobVersionedHashes", "UNSUPPORTED_OPERATION", {
 
-                         operation: "_getTransactionPostData",
 
-                         info: { transaction }
 
-                     });
 
-                 }
 
-                 else {
 
-                     value = hexlify(value);
 
-                 }
 
-                 result[key] = value;
 
-             }
 
-             return result;
 
-         }
 
-         /**
 
-          *  Throws the normalized Etherscan error.
 
-          */
 
-         _checkError(req, error, transaction) {
 
-             // Pull any message out if, possible
 
-             let message = "";
 
-             if (isError(error, "SERVER_ERROR")) {
 
-                 // Check for an error emitted by a proxy call
 
-                 try {
 
-                     message = error.info.result.error.message;
 
-                 }
 
-                 catch (e) { }
 
-                 if (!message) {
 
-                     try {
 
-                         message = error.info.message;
 
-                     }
 
-                     catch (e) { }
 
-                 }
 
-             }
 
-             if (req.method === "estimateGas") {
 
-                 if (!message.match(/revert/i) && message.match(/insufficient funds/i)) {
 
-                     assert(false, "insufficient funds", "INSUFFICIENT_FUNDS", {
 
-                         transaction: req.transaction
 
-                     });
 
-                 }
 
-             }
 
-             if (req.method === "call" || req.method === "estimateGas") {
 
-                 if (message.match(/execution reverted/i)) {
 
-                     let data = "";
 
-                     try {
 
-                         data = error.info.result.error.data;
 
-                     }
 
-                     catch (error) { }
 
-                     const e = AbiCoder.getBuiltinCallException(req.method, req.transaction, data);
 
-                     e.info = { request: req, error };
 
-                     throw e;
 
-                 }
 
-             }
 
-             if (message) {
 
-                 if (req.method === "broadcastTransaction") {
 
-                     const transaction = Transaction.from(req.signedTransaction);
 
-                     if (message.match(/replacement/i) && message.match(/underpriced/i)) {
 
-                         assert(false, "replacement fee too low", "REPLACEMENT_UNDERPRICED", {
 
-                             transaction
 
-                         });
 
-                     }
 
-                     if (message.match(/insufficient funds/)) {
 
-                         assert(false, "insufficient funds for intrinsic transaction cost", "INSUFFICIENT_FUNDS", {
 
-                             transaction
 
-                         });
 
-                     }
 
-                     if (message.match(/same hash was already imported|transaction nonce is too low|nonce too low/)) {
 
-                         assert(false, "nonce has already been used", "NONCE_EXPIRED", {
 
-                             transaction
 
-                         });
 
-                     }
 
-                 }
 
-             }
 
-             // Something we could not process
 
-             throw error;
 
-         }
 
-         async _detectNetwork() {
 
-             return this.network;
 
-         }
 
-         async _perform(req) {
 
-             switch (req.method) {
 
-                 case "chainId":
 
-                     return this.network.chainId;
 
-                 case "getBlockNumber":
 
-                     return this.fetch("proxy", { action: "eth_blockNumber" });
 
-                 case "getGasPrice":
 
-                     return this.fetch("proxy", { action: "eth_gasPrice" });
 
-                 case "getPriorityFee":
 
-                     // This is temporary until Etherscan completes support
 
-                     if (this.network.name === "mainnet") {
 
-                         return "1000000000";
 
-                     }
 
-                     else if (this.network.name === "optimism") {
 
-                         return "1000000";
 
-                     }
 
-                     else {
 
-                         throw new Error("fallback onto the AbstractProvider default");
 
-                     }
 
-                 /* Working with Etherscan to get this added:
 
-                 try {
 
-                     const test = await this.fetch("proxy", {
 
-                         action: "eth_maxPriorityFeePerGas"
 
-                     });
 
-                     console.log(test);
 
-                     return test;
 
-                 } catch (e) {
 
-                     console.log("DEBUG", e);
 
-                     throw e;
 
-                 }
 
-                 */
 
-                 /* This might be safe; but due to rounding neither myself
 
-                    or Etherscan are necessarily comfortable with this. :)
 
-                 try {
 
-                     const result = await this.fetch("gastracker", { action: "gasoracle" });
 
-                     console.log(result);
 
-                     const gasPrice = parseUnits(result.SafeGasPrice, "gwei");
 
-                     const baseFee = parseUnits(result.suggestBaseFee, "gwei");
 
-                     const priorityFee = gasPrice - baseFee;
 
-                     if (priorityFee < 0) { throw new Error("negative priority fee; defer to abstract provider default"); }
 
-                     return priorityFee;
 
-                 } catch (error) {
 
-                     console.log("DEBUG", error);
 
-                     throw error;
 
-                 }
 
-                 */
 
-                 case "getBalance":
 
-                     // Returns base-10 result
 
-                     return this.fetch("account", {
 
-                         action: "balance",
 
-                         address: req.address,
 
-                         tag: req.blockTag
 
-                     });
 
-                 case "getTransactionCount":
 
-                     return this.fetch("proxy", {
 
-                         action: "eth_getTransactionCount",
 
-                         address: req.address,
 
-                         tag: req.blockTag
 
-                     });
 
-                 case "getCode":
 
-                     return this.fetch("proxy", {
 
-                         action: "eth_getCode",
 
-                         address: req.address,
 
-                         tag: req.blockTag
 
-                     });
 
-                 case "getStorage":
 
-                     return this.fetch("proxy", {
 
-                         action: "eth_getStorageAt",
 
-                         address: req.address,
 
-                         position: req.position,
 
-                         tag: req.blockTag
 
-                     });
 
-                 case "broadcastTransaction":
 
-                     return this.fetch("proxy", {
 
-                         action: "eth_sendRawTransaction",
 
-                         hex: req.signedTransaction
 
-                     }, true).catch((error) => {
 
-                         return this._checkError(req, error, req.signedTransaction);
 
-                     });
 
-                 case "getBlock":
 
-                     if ("blockTag" in req) {
 
-                         return this.fetch("proxy", {
 
-                             action: "eth_getBlockByNumber",
 
-                             tag: req.blockTag,
 
-                             boolean: (req.includeTransactions ? "true" : "false")
 
-                         });
 
-                     }
 
-                     assert(false, "getBlock by blockHash not supported by Etherscan", "UNSUPPORTED_OPERATION", {
 
-                         operation: "getBlock(blockHash)"
 
-                     });
 
-                 case "getTransaction":
 
-                     return this.fetch("proxy", {
 
-                         action: "eth_getTransactionByHash",
 
-                         txhash: req.hash
 
-                     });
 
-                 case "getTransactionReceipt":
 
-                     return this.fetch("proxy", {
 
-                         action: "eth_getTransactionReceipt",
 
-                         txhash: req.hash
 
-                     });
 
-                 case "call": {
 
-                     if (req.blockTag !== "latest") {
 
-                         throw new Error("EtherscanProvider does not support blockTag for call");
 
-                     }
 
-                     const postData = this._getTransactionPostData(req.transaction);
 
-                     postData.module = "proxy";
 
-                     postData.action = "eth_call";
 
-                     try {
 
-                         return await this.fetch("proxy", postData, true);
 
-                     }
 
-                     catch (error) {
 
-                         return this._checkError(req, error, req.transaction);
 
-                     }
 
-                 }
 
-                 case "estimateGas": {
 
-                     const postData = this._getTransactionPostData(req.transaction);
 
-                     postData.module = "proxy";
 
-                     postData.action = "eth_estimateGas";
 
-                     try {
 
-                         return await this.fetch("proxy", postData, true);
 
-                     }
 
-                     catch (error) {
 
-                         return this._checkError(req, error, req.transaction);
 
-                     }
 
-                 }
 
-             }
 
-             return super._perform(req);
 
-         }
 
-         async getNetwork() {
 
-             return this.network;
 
-         }
 
-         /**
 
-          *  Resolves to the current price of ether.
 
-          *
 
-          *  This returns ``0`` on any network other than ``mainnet``.
 
-          */
 
-         async getEtherPrice() {
 
-             if (this.network.name !== "mainnet") {
 
-                 return 0.0;
 
-             }
 
-             return parseFloat((await this.fetch("stats", { action: "ethprice" })).ethusd);
 
-         }
 
-         /**
 
-          *  Resolves to a [Contract]] for %%address%%, using the
 
-          *  Etherscan API to retreive the Contract ABI.
 
-          */
 
-         async getContract(_address) {
 
-             let address = this._getAddress(_address);
 
-             if (isPromise(address)) {
 
-                 address = await address;
 
-             }
 
-             try {
 
-                 const resp = await this.fetch("contract", {
 
-                     action: "getabi", address
 
-                 });
 
-                 const abi = JSON.parse(resp);
 
-                 return new Contract(address, abi, this);
 
-             }
 
-             catch (error) {
 
-                 return null;
 
-             }
 
-         }
 
-         isCommunityResource() {
 
-             return (this.apiKey == null);
 
-         }
 
-     }
 
-     function getGlobal() {
 
-         if (typeof self !== 'undefined') {
 
-             return self;
 
-         }
 
-         if (typeof window !== 'undefined') {
 
-             return window;
 
-         }
 
-         if (typeof global !== 'undefined') {
 
-             return global;
 
-         }
 
-         throw new Error('unable to locate global object');
 
-     }
 
-     const _WebSocket = getGlobal().WebSocket;
 
-     /**
 
-      *  Generic long-lived socket provider.
 
-      *
 
-      *  Sub-classing notes
 
-      *  - a sub-class MUST call the `_start()` method once connected
 
-      *  - a sub-class MUST override the `_write(string)` method
 
-      *  - a sub-class MUST call `_processMessage(string)` for each message
 
-      *
 
-      *  @_subsection: api/providers/abstract-provider:Socket Providers  [about-socketProvider]
 
-      */
 
-     /**
 
-      *  A **SocketSubscriber** uses a socket transport to handle events and
 
-      *  should use [[_emit]] to manage the events.
 
-      */
 
-     class SocketSubscriber {
 
-         #provider;
 
-         #filter;
 
-         /**
 
-          *  The filter.
 
-          */
 
-         get filter() { return JSON.parse(this.#filter); }
 
-         #filterId;
 
-         #paused;
 
-         #emitPromise;
 
-         /**
 
-          *  Creates a new **SocketSubscriber** attached to %%provider%% listening
 
-          *  to %%filter%%.
 
-          */
 
-         constructor(provider, filter) {
 
-             this.#provider = provider;
 
-             this.#filter = JSON.stringify(filter);
 
-             this.#filterId = null;
 
-             this.#paused = null;
 
-             this.#emitPromise = null;
 
-         }
 
-         start() {
 
-             this.#filterId = this.#provider.send("eth_subscribe", this.filter).then((filterId) => {
 
-                 this.#provider._register(filterId, this);
 
-                 return filterId;
 
-             });
 
-         }
 
-         stop() {
 
-             (this.#filterId).then((filterId) => {
 
-                 if (this.#provider.destroyed) {
 
-                     return;
 
-                 }
 
-                 this.#provider.send("eth_unsubscribe", [filterId]);
 
-             });
 
-             this.#filterId = null;
 
-         }
 
-         // @TODO: pause should trap the current blockNumber, unsub, and on resume use getLogs
 
-         //        and resume
 
-         pause(dropWhilePaused) {
 
-             assert(dropWhilePaused, "preserve logs while paused not supported by SocketSubscriber yet", "UNSUPPORTED_OPERATION", { operation: "pause(false)" });
 
-             this.#paused = !!dropWhilePaused;
 
-         }
 
-         resume() {
 
-             this.#paused = null;
 
-         }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         _handleMessage(message) {
 
-             if (this.#filterId == null) {
 
-                 return;
 
-             }
 
-             if (this.#paused === null) {
 
-                 let emitPromise = this.#emitPromise;
 
-                 if (emitPromise == null) {
 
-                     emitPromise = this._emit(this.#provider, message);
 
-                 }
 
-                 else {
 
-                     emitPromise = emitPromise.then(async () => {
 
-                         await this._emit(this.#provider, message);
 
-                     });
 
-                 }
 
-                 this.#emitPromise = emitPromise.then(() => {
 
-                     if (this.#emitPromise === emitPromise) {
 
-                         this.#emitPromise = null;
 
-                     }
 
-                 });
 
-             }
 
-         }
 
-         /**
 
-          *  Sub-classes **must** override this to emit the events on the
 
-          *  provider.
 
-          */
 
-         async _emit(provider, message) {
 
-             throw new Error("sub-classes must implemente this; _emit");
 
-         }
 
-     }
 
-     /**
 
-      *  A **SocketBlockSubscriber** listens for ``newHeads`` events and emits
 
-      *  ``"block"`` events.
 
-      */
 
-     class SocketBlockSubscriber extends SocketSubscriber {
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(provider) {
 
-             super(provider, ["newHeads"]);
 
-         }
 
-         async _emit(provider, message) {
 
-             provider.emit("block", parseInt(message.number));
 
-         }
 
-     }
 
-     /**
 
-      *  A **SocketPendingSubscriber** listens for pending transacitons and emits
 
-      *  ``"pending"`` events.
 
-      */
 
-     class SocketPendingSubscriber extends SocketSubscriber {
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(provider) {
 
-             super(provider, ["newPendingTransactions"]);
 
-         }
 
-         async _emit(provider, message) {
 
-             provider.emit("pending", message);
 
-         }
 
-     }
 
-     /**
 
-      *  A **SocketEventSubscriber** listens for event logs.
 
-      */
 
-     class SocketEventSubscriber extends SocketSubscriber {
 
-         #logFilter;
 
-         /**
 
-          *  The filter.
 
-          */
 
-         get logFilter() { return JSON.parse(this.#logFilter); }
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         constructor(provider, filter) {
 
-             super(provider, ["logs", filter]);
 
-             this.#logFilter = JSON.stringify(filter);
 
-         }
 
-         async _emit(provider, message) {
 
-             provider.emit(this.logFilter, provider._wrapLog(message, provider._network));
 
-         }
 
-     }
 
-     /**
 
-      *  A **SocketProvider** is backed by a long-lived connection over a
 
-      *  socket, which can subscribe and receive real-time messages over
 
-      *  its communication channel.
 
-      */
 
-     class SocketProvider extends JsonRpcApiProvider {
 
-         #callbacks;
 
-         // Maps each filterId to its subscriber
 
-         #subs;
 
-         // If any events come in before a subscriber has finished
 
-         // registering, queue them
 
-         #pending;
 
-         /**
 
-          *  Creates a new **SocketProvider** connected to %%network%%.
 
-          *
 
-          *  If unspecified, the network will be discovered.
 
-          */
 
-         constructor(network, _options) {
 
-             // Copy the options
 
-             const options = Object.assign({}, (_options != null) ? _options : {});
 
-             // Support for batches is generally not supported for
 
-             // connection-base providers; if this changes in the future
 
-             // the _send should be updated to reflect this
 
-             assertArgument(options.batchMaxCount == null || options.batchMaxCount === 1, "sockets-based providers do not support batches", "options.batchMaxCount", _options);
 
-             options.batchMaxCount = 1;
 
-             // Socket-based Providers (generally) cannot change their network,
 
-             // since they have a long-lived connection; but let people override
 
-             // this if they have just cause.
 
-             if (options.staticNetwork == null) {
 
-                 options.staticNetwork = true;
 
-             }
 
-             super(network, options);
 
-             this.#callbacks = new Map();
 
-             this.#subs = new Map();
 
-             this.#pending = new Map();
 
-         }
 
-         // This value is only valid after _start has been called
 
-         /*
 
-         get _network(): Network {
 
-             if (this.#network == null) {
 
-                 throw new Error("this shouldn't happen");
 
-             }
 
-             return this.#network.clone();
 
-         }
 
-         */
 
-         _getSubscriber(sub) {
 
-             switch (sub.type) {
 
-                 case "close":
 
-                     return new UnmanagedSubscriber("close");
 
-                 case "block":
 
-                     return new SocketBlockSubscriber(this);
 
-                 case "pending":
 
-                     return new SocketPendingSubscriber(this);
 
-                 case "event":
 
-                     return new SocketEventSubscriber(this, sub.filter);
 
-                 case "orphan":
 
-                     // Handled auto-matically within AbstractProvider
 
-                     // when the log.removed = true
 
-                     if (sub.filter.orphan === "drop-log") {
 
-                         return new UnmanagedSubscriber("drop-log");
 
-                     }
 
-             }
 
-             return super._getSubscriber(sub);
 
-         }
 
-         /**
 
-          *  Register a new subscriber. This is used internalled by Subscribers
 
-          *  and generally is unecessary unless extending capabilities.
 
-          */
 
-         _register(filterId, subscriber) {
 
-             this.#subs.set(filterId, subscriber);
 
-             const pending = this.#pending.get(filterId);
 
-             if (pending) {
 
-                 for (const message of pending) {
 
-                     subscriber._handleMessage(message);
 
-                 }
 
-                 this.#pending.delete(filterId);
 
-             }
 
-         }
 
-         async _send(payload) {
 
-             // WebSocket provider doesn't accept batches
 
-             assertArgument(!Array.isArray(payload), "WebSocket does not support batch send", "payload", payload);
 
-             // @TODO: stringify payloads here and store to prevent mutations
 
-             // Prepare a promise to respond to
 
-             const promise = new Promise((resolve, reject) => {
 
-                 this.#callbacks.set(payload.id, { payload, resolve, reject });
 
-             });
 
-             // Wait until the socket is connected before writing to it
 
-             await this._waitUntilReady();
 
-             // Write the request to the socket
 
-             await this._write(JSON.stringify(payload));
 
-             return [await promise];
 
-         }
 
-         // Sub-classes must call this once they are connected
 
-         /*
 
-         async _start(): Promise<void> {
 
-             if (this.#ready) { return; }
 
-             for (const { payload } of this.#callbacks.values()) {
 
-                 await this._write(JSON.stringify(payload));
 
-             }
 
-             this.#ready = (async function() {
 
-                 await super._start();
 
-             })();
 
-         }
 
-         */
 
-         /**
 
-          *  Sub-classes **must** call this with messages received over their
 
-          *  transport to be processed and dispatched.
 
-          */
 
-         async _processMessage(message) {
 
-             const result = (JSON.parse(message));
 
-             if (result && typeof (result) === "object" && "id" in result) {
 
-                 const callback = this.#callbacks.get(result.id);
 
-                 if (callback == null) {
 
-                     this.emit("error", makeError("received result for unknown id", "UNKNOWN_ERROR", {
 
-                         reasonCode: "UNKNOWN_ID",
 
-                         result
 
-                     }));
 
-                     return;
 
-                 }
 
-                 this.#callbacks.delete(result.id);
 
-                 callback.resolve(result);
 
-             }
 
-             else if (result && result.method === "eth_subscription") {
 
-                 const filterId = result.params.subscription;
 
-                 const subscriber = this.#subs.get(filterId);
 
-                 if (subscriber) {
 
-                     subscriber._handleMessage(result.params.result);
 
-                 }
 
-                 else {
 
-                     let pending = this.#pending.get(filterId);
 
-                     if (pending == null) {
 
-                         pending = [];
 
-                         this.#pending.set(filterId, pending);
 
-                     }
 
-                     pending.push(result.params.result);
 
-                 }
 
-             }
 
-             else {
 
-                 this.emit("error", makeError("received unexpected message", "UNKNOWN_ERROR", {
 
-                     reasonCode: "UNEXPECTED_MESSAGE",
 
-                     result
 
-                 }));
 
-                 return;
 
-             }
 
-         }
 
-         /**
 
-          *  Sub-classes **must** override this to send %%message%% over their
 
-          *  transport.
 
-          */
 
-         async _write(message) {
 
-             throw new Error("sub-classes must override this");
 
-         }
 
-     }
 
-     /**
 
-      *  A JSON-RPC provider which is backed by a WebSocket.
 
-      *
 
-      *  WebSockets are often preferred because they retain a live connection
 
-      *  to a server, which permits more instant access to events.
 
-      *
 
-      *  However, this incurs higher server infrasturture costs, so additional
 
-      *  resources may be required to host your own WebSocket nodes and many
 
-      *  third-party services charge additional fees for WebSocket endpoints.
 
-      */
 
-     class WebSocketProvider extends SocketProvider {
 
-         #connect;
 
-         #websocket;
 
-         get websocket() {
 
-             if (this.#websocket == null) {
 
-                 throw new Error("websocket closed");
 
-             }
 
-             return this.#websocket;
 
-         }
 
-         constructor(url, network, options) {
 
-             super(network, options);
 
-             if (typeof (url) === "string") {
 
-                 this.#connect = () => { return new _WebSocket(url); };
 
-                 this.#websocket = this.#connect();
 
-             }
 
-             else if (typeof (url) === "function") {
 
-                 this.#connect = url;
 
-                 this.#websocket = url();
 
-             }
 
-             else {
 
-                 this.#connect = null;
 
-                 this.#websocket = url;
 
-             }
 
-             this.websocket.onopen = async () => {
 
-                 try {
 
-                     await this._start();
 
-                     this.resume();
 
-                 }
 
-                 catch (error) {
 
-                     console.log("failed to start WebsocketProvider", error);
 
-                     // @TODO: now what? Attempt reconnect?
 
-                 }
 
-             };
 
-             this.websocket.onmessage = (message) => {
 
-                 this._processMessage(message.data);
 
-             };
 
-             /*
 
-                     this.websocket.onclose = (event) => {
 
-                         // @TODO: What event.code should we reconnect on?
 
-                         const reconnect = false;
 
-                         if (reconnect) {
 
-                             this.pause(true);
 
-                             if (this.#connect) {
 
-                                 this.#websocket = this.#connect();
 
-                                 this.#websocket.onopen = ...
 
-                                 // @TODO: this requires the super class to rebroadcast; move it there
 
-                             }
 
-                             this._reconnect();
 
-                         }
 
-                     };
 
-             */
 
-         }
 
-         async _write(message) {
 
-             this.websocket.send(message);
 
-         }
 
-         async destroy() {
 
-             if (this.#websocket != null) {
 
-                 this.#websocket.close();
 
-                 this.#websocket = null;
 
-             }
 
-             super.destroy();
 
-         }
 
-     }
 
-     /**
 
-      *  [[link-infura]] provides a third-party service for connecting to
 
-      *  various blockchains over JSON-RPC.
 
-      *
 
-      *  **Supported Networks**
 
-      *
 
-      *  - Ethereum Mainnet (``mainnet``)
 
-      *  - Goerli Testnet (``goerli``)
 
-      *  - Sepolia Testnet (``sepolia``)
 
-      *  - Arbitrum (``arbitrum``)
 
-      *  - Arbitrum Goerli Testnet (``arbitrum-goerli``)
 
-      *  - Arbitrum Sepolia Testnet (``arbitrum-sepolia``)
 
-      *  - Base (``base``)
 
-      *  - Base Goerlia Testnet (``base-goerli``)
 
-      *  - Base Sepolia Testnet (``base-sepolia``)
 
-      *  - BNB Smart Chain Mainnet (``bnb``)
 
-      *  - BNB Smart Chain Testnet (``bnbt``)
 
-      *  - Linea (``linea``)
 
-      *  - Linea Goerli Testnet (``linea-goerli``)
 
-      *  - Linea Sepolia Testnet (``linea-sepolia``)
 
-      *  - Optimism (``optimism``)
 
-      *  - Optimism Goerli Testnet (``optimism-goerli``)
 
-      *  - Optimism Sepolia Testnet (``optimism-sepolia``)
 
-      *  - Polygon (``matic``)
 
-      *  - Polygon Amoy Testnet (``matic-amoy``)
 
-      *  - Polygon Mumbai Testnet (``matic-mumbai``)
 
-      *
 
-      *  @_subsection: api/providers/thirdparty:INFURA  [providers-infura]
 
-      */
 
-     const defaultProjectId = "84842078b09946638c03157f83405213";
 
-     function getHost$2(name) {
 
-         switch (name) {
 
-             case "mainnet":
 
-                 return "mainnet.infura.io";
 
-             case "goerli":
 
-                 return "goerli.infura.io";
 
-             case "sepolia":
 
-                 return "sepolia.infura.io";
 
-             case "arbitrum":
 
-                 return "arbitrum-mainnet.infura.io";
 
-             case "arbitrum-goerli":
 
-                 return "arbitrum-goerli.infura.io";
 
-             case "arbitrum-sepolia":
 
-                 return "arbitrum-sepolia.infura.io";
 
-             case "base":
 
-                 return "base-mainnet.infura.io";
 
-             case "base-goerlia":
 
-                 return "base-goerli.infura.io";
 
-             case "base-sepolia":
 
-                 return "base-sepolia.infura.io";
 
-             case "bnb":
 
-                 return "bnbsmartchain-mainnet.infura.io";
 
-             case "bnbt":
 
-                 return "bnbsmartchain-testnet.infura.io";
 
-             case "linea":
 
-                 return "linea-mainnet.infura.io";
 
-             case "linea-goerli":
 
-                 return "linea-goerli.infura.io";
 
-             case "linea-sepolia":
 
-                 return "linea-sepolia.infura.io";
 
-             case "matic":
 
-                 return "polygon-mainnet.infura.io";
 
-             case "matic-amoy":
 
-                 return "polygon-amoy.infura.io";
 
-             case "matic-mumbai":
 
-                 return "polygon-mumbai.infura.io";
 
-             case "optimism":
 
-                 return "optimism-mainnet.infura.io";
 
-             case "optimism-goerli":
 
-                 return "optimism-goerli.infura.io";
 
-             case "optimism-sepolia":
 
-                 return "optimism-sepolia.infura.io";
 
-         }
 
-         assertArgument(false, "unsupported network", "network", name);
 
-     }
 
-     /**
 
-      *  The **InfuraWebSocketProvider** connects to the [[link-infura]]
 
-      *  WebSocket end-points.
 
-      *
 
-      *  By default, a highly-throttled API key is used, which is
 
-      *  appropriate for quick prototypes and simple scripts. To
 
-      *  gain access to an increased rate-limit, it is highly
 
-      *  recommended to [sign up here](link-infura-signup).
 
-      */
 
-     class InfuraWebSocketProvider extends WebSocketProvider {
 
-         /**
 
-          *  The Project ID for the INFURA connection.
 
-          */
 
-         projectId;
 
-         /**
 
-          *  The Project Secret.
 
-          *
 
-          *  If null, no authenticated requests are made. This should not
 
-          *  be used outside of private contexts.
 
-          */
 
-         projectSecret;
 
-         /**
 
-          *  Creates a new **InfuraWebSocketProvider**.
 
-          */
 
-         constructor(network, projectId) {
 
-             const provider = new InfuraProvider(network, projectId);
 
-             const req = provider._getConnection();
 
-             assert(!req.credentials, "INFURA WebSocket project secrets unsupported", "UNSUPPORTED_OPERATION", { operation: "InfuraProvider.getWebSocketProvider()" });
 
-             const url = req.url.replace(/^http/i, "ws").replace("/v3/", "/ws/v3/");
 
-             super(url, provider._network);
 
-             defineProperties(this, {
 
-                 projectId: provider.projectId,
 
-                 projectSecret: provider.projectSecret
 
-             });
 
-         }
 
-         isCommunityResource() {
 
-             return (this.projectId === defaultProjectId);
 
-         }
 
-     }
 
-     /**
 
-      *  The **InfuraProvider** connects to the [[link-infura]]
 
-      *  JSON-RPC end-points.
 
-      *
 
-      *  By default, a highly-throttled API key is used, which is
 
-      *  appropriate for quick prototypes and simple scripts. To
 
-      *  gain access to an increased rate-limit, it is highly
 
-      *  recommended to [sign up here](link-infura-signup).
 
-      */
 
-     class InfuraProvider extends JsonRpcProvider {
 
-         /**
 
-          *  The Project ID for the INFURA connection.
 
-          */
 
-         projectId;
 
-         /**
 
-          *  The Project Secret.
 
-          *
 
-          *  If null, no authenticated requests are made. This should not
 
-          *  be used outside of private contexts.
 
-          */
 
-         projectSecret;
 
-         /**
 
-          *  Creates a new **InfuraProvider**.
 
-          */
 
-         constructor(_network, projectId, projectSecret) {
 
-             if (_network == null) {
 
-                 _network = "mainnet";
 
-             }
 
-             const network = Network.from(_network);
 
-             if (projectId == null) {
 
-                 projectId = defaultProjectId;
 
-             }
 
-             if (projectSecret == null) {
 
-                 projectSecret = null;
 
-             }
 
-             const request = InfuraProvider.getRequest(network, projectId, projectSecret);
 
-             super(request, network, { staticNetwork: network });
 
-             defineProperties(this, { projectId, projectSecret });
 
-         }
 
-         _getProvider(chainId) {
 
-             try {
 
-                 return new InfuraProvider(chainId, this.projectId, this.projectSecret);
 
-             }
 
-             catch (error) { }
 
-             return super._getProvider(chainId);
 
-         }
 
-         isCommunityResource() {
 
-             return (this.projectId === defaultProjectId);
 
-         }
 
-         /**
 
-          *  Creates a new **InfuraWebSocketProvider**.
 
-          */
 
-         static getWebSocketProvider(network, projectId) {
 
-             return new InfuraWebSocketProvider(network, projectId);
 
-         }
 
-         /**
 
-          *  Returns a prepared request for connecting to %%network%%
 
-          *  with %%projectId%% and %%projectSecret%%.
 
-          */
 
-         static getRequest(network, projectId, projectSecret) {
 
-             if (projectId == null) {
 
-                 projectId = defaultProjectId;
 
-             }
 
-             if (projectSecret == null) {
 
-                 projectSecret = null;
 
-             }
 
-             const request = new FetchRequest(`https:/\/${getHost$2(network.name)}/v3/${projectId}`);
 
-             request.allowGzip = true;
 
-             if (projectSecret) {
 
-                 request.setCredentials("", projectSecret);
 
-             }
 
-             if (projectId === defaultProjectId) {
 
-                 request.retryFunc = async (request, response, attempt) => {
 
-                     showThrottleMessage("InfuraProvider");
 
-                     return true;
 
-                 };
 
-             }
 
-             return request;
 
-         }
 
-     }
 
-     /**
 
-      *  [[link-quicknode]] provides a third-party service for connecting to
 
-      *  various blockchains over JSON-RPC.
 
-      *
 
-      *  **Supported Networks**
 
-      *
 
-      *  - Ethereum Mainnet (``mainnet``)
 
-      *  - Goerli Testnet (``goerli``)
 
-      *  - Sepolia Testnet (``sepolia``)
 
-      *  - Holesky Testnet (``holesky``)
 
-      *  - Arbitrum (``arbitrum``)
 
-      *  - Arbitrum Goerli Testnet (``arbitrum-goerli``)
 
-      *  - Arbitrum Sepolia Testnet (``arbitrum-sepolia``)
 
-      *  - Base Mainnet (``base``);
 
-      *  - Base Goerli Testnet (``base-goerli``);
 
-      *  - Base Sepolia Testnet (``base-sepolia``);
 
-      *  - BNB Smart Chain Mainnet (``bnb``)
 
-      *  - BNB Smart Chain Testnet (``bnbt``)
 
-      *  - Optimism (``optimism``)
 
-      *  - Optimism Goerli Testnet (``optimism-goerli``)
 
-      *  - Optimism Sepolia Testnet (``optimism-sepolia``)
 
-      *  - Polygon (``matic``)
 
-      *  - Polygon Mumbai Testnet (``matic-mumbai``)
 
-      *
 
-      *  @_subsection: api/providers/thirdparty:QuickNode  [providers-quicknode]
 
-      */
 
-     const defaultToken = "919b412a057b5e9c9b6dce193c5a60242d6efadb";
 
-     function getHost$1(name) {
 
-         switch (name) {
 
-             case "mainnet":
 
-                 return "ethers.quiknode.pro";
 
-             case "goerli":
 
-                 return "ethers.ethereum-goerli.quiknode.pro";
 
-             case "sepolia":
 
-                 return "ethers.ethereum-sepolia.quiknode.pro";
 
-             case "holesky":
 
-                 return "ethers.ethereum-holesky.quiknode.pro";
 
-             case "arbitrum":
 
-                 return "ethers.arbitrum-mainnet.quiknode.pro";
 
-             case "arbitrum-goerli":
 
-                 return "ethers.arbitrum-goerli.quiknode.pro";
 
-             case "arbitrum-sepolia":
 
-                 return "ethers.arbitrum-sepolia.quiknode.pro";
 
-             case "base":
 
-                 return "ethers.base-mainnet.quiknode.pro";
 
-             case "base-goerli":
 
-                 return "ethers.base-goerli.quiknode.pro";
 
-             case "base-spolia":
 
-                 return "ethers.base-sepolia.quiknode.pro";
 
-             case "bnb":
 
-                 return "ethers.bsc.quiknode.pro";
 
-             case "bnbt":
 
-                 return "ethers.bsc-testnet.quiknode.pro";
 
-             case "matic":
 
-                 return "ethers.matic.quiknode.pro";
 
-             case "matic-mumbai":
 
-                 return "ethers.matic-testnet.quiknode.pro";
 
-             case "optimism":
 
-                 return "ethers.optimism.quiknode.pro";
 
-             case "optimism-goerli":
 
-                 return "ethers.optimism-goerli.quiknode.pro";
 
-             case "optimism-sepolia":
 
-                 return "ethers.optimism-sepolia.quiknode.pro";
 
-             case "xdai":
 
-                 return "ethers.xdai.quiknode.pro";
 
-         }
 
-         assertArgument(false, "unsupported network", "network", name);
 
-     }
 
-     /*
 
-     @TODO:
 
-       These networks are not currently present in the Network
 
-       default included networks. Research them and ensure they
 
-       are EVM compatible and work with ethers
 
-       http://ethers.matic-amoy.quiknode.pro
 
-       http://ethers.avalanche-mainnet.quiknode.pro
 
-       http://ethers.avalanche-testnet.quiknode.pro
 
-       http://ethers.blast-sepolia.quiknode.pro
 
-       http://ethers.celo-mainnet.quiknode.pro
 
-       http://ethers.fantom.quiknode.pro
 
-       http://ethers.imx-demo.quiknode.pro
 
-       http://ethers.imx-mainnet.quiknode.pro
 
-       http://ethers.imx-testnet.quiknode.pro
 
-       http://ethers.near-mainnet.quiknode.pro
 
-       http://ethers.near-testnet.quiknode.pro
 
-       http://ethers.nova-mainnet.quiknode.pro
 
-       http://ethers.scroll-mainnet.quiknode.pro
 
-       http://ethers.scroll-testnet.quiknode.pro
 
-       http://ethers.tron-mainnet.quiknode.pro
 
-       http://ethers.zkevm-mainnet.quiknode.pro
 
-       http://ethers.zkevm-testnet.quiknode.pro
 
-       http://ethers.zksync-mainnet.quiknode.pro
 
-       http://ethers.zksync-testnet.quiknode.pro
 
-     */
 
-     /**
 
-      *  The **QuickNodeProvider** connects to the [[link-quicknode]]
 
-      *  JSON-RPC end-points.
 
-      *
 
-      *  By default, a highly-throttled API token is used, which is
 
-      *  appropriate for quick prototypes and simple scripts. To
 
-      *  gain access to an increased rate-limit, it is highly
 
-      *  recommended to [sign up here](link-quicknode).
 
-      */
 
-     class QuickNodeProvider extends JsonRpcProvider {
 
-         /**
 
-          *  The API token.
 
-          */
 
-         token;
 
-         /**
 
-          *  Creates a new **QuickNodeProvider**.
 
-          */
 
-         constructor(_network, token) {
 
-             if (_network == null) {
 
-                 _network = "mainnet";
 
-             }
 
-             const network = Network.from(_network);
 
-             if (token == null) {
 
-                 token = defaultToken;
 
-             }
 
-             const request = QuickNodeProvider.getRequest(network, token);
 
-             super(request, network, { staticNetwork: network });
 
-             defineProperties(this, { token });
 
-         }
 
-         _getProvider(chainId) {
 
-             try {
 
-                 return new QuickNodeProvider(chainId, this.token);
 
-             }
 
-             catch (error) { }
 
-             return super._getProvider(chainId);
 
-         }
 
-         isCommunityResource() {
 
-             return (this.token === defaultToken);
 
-         }
 
-         /**
 
-          *  Returns a new request prepared for %%network%% and the
 
-          *  %%token%%.
 
-          */
 
-         static getRequest(network, token) {
 
-             if (token == null) {
 
-                 token = defaultToken;
 
-             }
 
-             const request = new FetchRequest(`https:/\/${getHost$1(network.name)}/${token}`);
 
-             request.allowGzip = true;
 
-             //if (projectSecret) { request.setCredentials("", projectSecret); }
 
-             if (token === defaultToken) {
 
-                 request.retryFunc = async (request, response, attempt) => {
 
-                     showThrottleMessage("QuickNodeProvider");
 
-                     return true;
 
-                 };
 
-             }
 
-             return request;
 
-         }
 
-     }
 
-     /**
 
-      *  A **FallbackProvider** provides resilience, security and performance
 
-      *  in a way that is customizable and configurable.
 
-      *
 
-      *  @_section: api/providers/fallback-provider:Fallback Provider [about-fallback-provider]
 
-      */
 
-     const BN_1 = BigInt("1");
 
-     const BN_2 = BigInt("2");
 
-     function shuffle(array) {
 
-         for (let i = array.length - 1; i > 0; i--) {
 
-             const j = Math.floor(Math.random() * (i + 1));
 
-             const tmp = array[i];
 
-             array[i] = array[j];
 
-             array[j] = tmp;
 
-         }
 
-     }
 
-     function stall$2(duration) {
 
-         return new Promise((resolve) => { setTimeout(resolve, duration); });
 
-     }
 
-     function getTime() { return (new Date()).getTime(); }
 
-     function stringify(value) {
 
-         return JSON.stringify(value, (key, value) => {
 
-             if (typeof (value) === "bigint") {
 
-                 return { type: "bigint", value: value.toString() };
 
-             }
 
-             return value;
 
-         });
 
-     }
 
-     const defaultConfig = { stallTimeout: 400, priority: 1, weight: 1 };
 
-     const defaultState = {
 
-         blockNumber: -2, requests: 0, lateResponses: 0, errorResponses: 0,
 
-         outOfSync: -1, unsupportedEvents: 0, rollingDuration: 0, score: 0,
 
-         _network: null, _updateNumber: null, _totalTime: 0,
 
-         _lastFatalError: null, _lastFatalErrorTimestamp: 0
 
-     };
 
-     async function waitForSync(config, blockNumber) {
 
-         while (config.blockNumber < 0 || config.blockNumber < blockNumber) {
 
-             if (!config._updateNumber) {
 
-                 config._updateNumber = (async () => {
 
-                     try {
 
-                         const blockNumber = await config.provider.getBlockNumber();
 
-                         if (blockNumber > config.blockNumber) {
 
-                             config.blockNumber = blockNumber;
 
-                         }
 
-                     }
 
-                     catch (error) {
 
-                         config.blockNumber = -2;
 
-                         config._lastFatalError = error;
 
-                         config._lastFatalErrorTimestamp = getTime();
 
-                     }
 
-                     config._updateNumber = null;
 
-                 })();
 
-             }
 
-             await config._updateNumber;
 
-             config.outOfSync++;
 
-             if (config._lastFatalError) {
 
-                 break;
 
-             }
 
-         }
 
-     }
 
-     function _normalize(value) {
 
-         if (value == null) {
 
-             return "null";
 
-         }
 
-         if (Array.isArray(value)) {
 
-             return "[" + (value.map(_normalize)).join(",") + "]";
 
-         }
 
-         if (typeof (value) === "object" && typeof (value.toJSON) === "function") {
 
-             return _normalize(value.toJSON());
 
-         }
 
-         switch (typeof (value)) {
 
-             case "boolean":
 
-             case "symbol":
 
-                 return value.toString();
 
-             case "bigint":
 
-             case "number":
 
-                 return BigInt(value).toString();
 
-             case "string":
 
-                 return JSON.stringify(value);
 
-             case "object": {
 
-                 const keys = Object.keys(value);
 
-                 keys.sort();
 
-                 return "{" + keys.map((k) => `${JSON.stringify(k)}:${_normalize(value[k])}`).join(",") + "}";
 
-             }
 
-         }
 
-         console.log("Could not serialize", value);
 
-         throw new Error("Hmm...");
 
-     }
 
-     function normalizeResult(value) {
 
-         if ("error" in value) {
 
-             const error = value.error;
 
-             return { tag: _normalize(error), value: error };
 
-         }
 
-         const result = value.result;
 
-         return { tag: _normalize(result), value: result };
 
-     }
 
-     // This strategy picks the highest weight result, as long as the weight is
 
-     // equal to or greater than quorum
 
-     function checkQuorum(quorum, results) {
 
-         const tally = new Map();
 
-         for (const { value, tag, weight } of results) {
 
-             const t = tally.get(tag) || { value, weight: 0 };
 
-             t.weight += weight;
 
-             tally.set(tag, t);
 
-         }
 
-         let best = null;
 
-         for (const r of tally.values()) {
 
-             if (r.weight >= quorum && (!best || r.weight > best.weight)) {
 
-                 best = r;
 
-             }
 
-         }
 
-         if (best) {
 
-             return best.value;
 
-         }
 
-         return undefined;
 
-     }
 
-     function getMedian(quorum, results) {
 
-         let resultWeight = 0;
 
-         const errorMap = new Map();
 
-         let bestError = null;
 
-         const values = [];
 
-         for (const { value, tag, weight } of results) {
 
-             if (value instanceof Error) {
 
-                 const e = errorMap.get(tag) || { value, weight: 0 };
 
-                 e.weight += weight;
 
-                 errorMap.set(tag, e);
 
-                 if (bestError == null || e.weight > bestError.weight) {
 
-                     bestError = e;
 
-                 }
 
-             }
 
-             else {
 
-                 values.push(BigInt(value));
 
-                 resultWeight += weight;
 
-             }
 
-         }
 
-         if (resultWeight < quorum) {
 
-             // We have quorum for an error
 
-             if (bestError && bestError.weight >= quorum) {
 
-                 return bestError.value;
 
-             }
 
-             // We do not have quorum for a result
 
-             return undefined;
 
-         }
 
-         // Get the sorted values
 
-         values.sort((a, b) => ((a < b) ? -1 : (b > a) ? 1 : 0));
 
-         const mid = Math.floor(values.length / 2);
 
-         // Odd-length; take the middle value
 
-         if (values.length % 2) {
 
-             return values[mid];
 
-         }
 
-         // Even length; take the ceiling of the mean of the center two values
 
-         return (values[mid - 1] + values[mid] + BN_1) / BN_2;
 
-     }
 
-     function getAnyResult(quorum, results) {
 
-         // If any value or error meets quorum, that is our preferred result
 
-         const result = checkQuorum(quorum, results);
 
-         if (result !== undefined) {
 
-             return result;
 
-         }
 
-         // Otherwise, do we have any result?
 
-         for (const r of results) {
 
-             if (r.value) {
 
-                 return r.value;
 
-             }
 
-         }
 
-         // Nope!
 
-         return undefined;
 
-     }
 
-     function getFuzzyMode(quorum, results) {
 
-         if (quorum === 1) {
 
-             return getNumber(getMedian(quorum, results), "%internal");
 
-         }
 
-         const tally = new Map();
 
-         const add = (result, weight) => {
 
-             const t = tally.get(result) || { result, weight: 0 };
 
-             t.weight += weight;
 
-             tally.set(result, t);
 
-         };
 
-         for (const { weight, value } of results) {
 
-             const r = getNumber(value);
 
-             add(r - 1, weight);
 
-             add(r, weight);
 
-             add(r + 1, weight);
 
-         }
 
-         let bestWeight = 0;
 
-         let bestResult = undefined;
 
-         for (const { weight, result } of tally.values()) {
 
-             // Use this result, if this result meets quorum and has either:
 
-             // - a better weight
 
-             // - or equal weight, but the result is larger
 
-             if (weight >= quorum && (weight > bestWeight || (bestResult != null && weight === bestWeight && result > bestResult))) {
 
-                 bestWeight = weight;
 
-                 bestResult = result;
 
-             }
 
-         }
 
-         return bestResult;
 
-     }
 
-     /**
 
-      *  A **FallbackProvider** manages several [[Providers]] providing
 
-      *  resilience by switching between slow or misbehaving nodes, security
 
-      *  by requiring multiple backends to aggree and performance by allowing
 
-      *  faster backends to respond earlier.
 
-      *
 
-      */
 
-     class FallbackProvider extends AbstractProvider {
 
-         /**
 
-          *  The number of backends that must agree on a value before it is
 
-          *  accpeted.
 
-          */
 
-         quorum;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         eventQuorum;
 
-         /**
 
-          *  @_ignore:
 
-          */
 
-         eventWorkers;
 
-         #configs;
 
-         #height;
 
-         #initialSyncPromise;
 
-         /**
 
-          *  Creates a new **FallbackProvider** with %%providers%% connected to
 
-          *  %%network%%.
 
-          *
 
-          *  If a [[Provider]] is included in %%providers%%, defaults are used
 
-          *  for the configuration.
 
-          */
 
-         constructor(providers, network, options) {
 
-             super(network, options);
 
-             this.#configs = providers.map((p) => {
 
-                 if (p instanceof AbstractProvider) {
 
-                     return Object.assign({ provider: p }, defaultConfig, defaultState);
 
-                 }
 
-                 else {
 
-                     return Object.assign({}, defaultConfig, p, defaultState);
 
-                 }
 
-             });
 
-             this.#height = -2;
 
-             this.#initialSyncPromise = null;
 
-             if (options && options.quorum != null) {
 
-                 this.quorum = options.quorum;
 
-             }
 
-             else {
 
-                 this.quorum = Math.ceil(this.#configs.reduce((accum, config) => {
 
-                     accum += config.weight;
 
-                     return accum;
 
-                 }, 0) / 2);
 
-             }
 
-             this.eventQuorum = 1;
 
-             this.eventWorkers = 1;
 
-             assertArgument(this.quorum <= this.#configs.reduce((a, c) => (a + c.weight), 0), "quorum exceed provider weight", "quorum", this.quorum);
 
-         }
 
-         get providerConfigs() {
 
-             return this.#configs.map((c) => {
 
-                 const result = Object.assign({}, c);
 
-                 for (const key in result) {
 
-                     if (key[0] === "_") {
 
-                         delete result[key];
 
-                     }
 
-                 }
 
-                 return result;
 
-             });
 
-         }
 
-         async _detectNetwork() {
 
-             return Network.from(getBigInt(await this._perform({ method: "chainId" })));
 
-         }
 
-         // @TODO: Add support to select providers to be the event subscriber
 
-         //_getSubscriber(sub: Subscription): Subscriber {
 
-         //    throw new Error("@TODO");
 
-         //}
 
-         /**
 
-          *  Transforms a %%req%% into the correct method call on %%provider%%.
 
-          */
 
-         async _translatePerform(provider, req) {
 
-             switch (req.method) {
 
-                 case "broadcastTransaction":
 
-                     return await provider.broadcastTransaction(req.signedTransaction);
 
-                 case "call":
 
-                     return await provider.call(Object.assign({}, req.transaction, { blockTag: req.blockTag }));
 
-                 case "chainId":
 
-                     return (await provider.getNetwork()).chainId;
 
-                 case "estimateGas":
 
-                     return await provider.estimateGas(req.transaction);
 
-                 case "getBalance":
 
-                     return await provider.getBalance(req.address, req.blockTag);
 
-                 case "getBlock": {
 
-                     const block = ("blockHash" in req) ? req.blockHash : req.blockTag;
 
-                     return await provider.getBlock(block, req.includeTransactions);
 
-                 }
 
-                 case "getBlockNumber":
 
-                     return await provider.getBlockNumber();
 
-                 case "getCode":
 
-                     return await provider.getCode(req.address, req.blockTag);
 
-                 case "getGasPrice":
 
-                     return (await provider.getFeeData()).gasPrice;
 
-                 case "getPriorityFee":
 
-                     return (await provider.getFeeData()).maxPriorityFeePerGas;
 
-                 case "getLogs":
 
-                     return await provider.getLogs(req.filter);
 
-                 case "getStorage":
 
-                     return await provider.getStorage(req.address, req.position, req.blockTag);
 
-                 case "getTransaction":
 
-                     return await provider.getTransaction(req.hash);
 
-                 case "getTransactionCount":
 
-                     return await provider.getTransactionCount(req.address, req.blockTag);
 
-                 case "getTransactionReceipt":
 
-                     return await provider.getTransactionReceipt(req.hash);
 
-                 case "getTransactionResult":
 
-                     return await provider.getTransactionResult(req.hash);
 
-             }
 
-         }
 
-         // Grab the next (random) config that is not already part of
 
-         // the running set
 
-         #getNextConfig(running) {
 
-             // @TODO: Maybe do a check here to favour (heavily) providers that
 
-             //        do not require waitForSync and disfavour providers that
 
-             //        seem down-ish or are behaving slowly
 
-             const configs = Array.from(running).map((r) => r.config);
 
-             // Shuffle the states, sorted by priority
 
-             const allConfigs = this.#configs.slice();
 
-             shuffle(allConfigs);
 
-             allConfigs.sort((a, b) => (a.priority - b.priority));
 
-             for (const config of allConfigs) {
 
-                 if (config._lastFatalError) {
 
-                     continue;
 
-                 }
 
-                 if (configs.indexOf(config) === -1) {
 
-                     return config;
 
-                 }
 
-             }
 
-             return null;
 
-         }
 
-         // Adds a new runner (if available) to running.
 
-         #addRunner(running, req) {
 
-             const config = this.#getNextConfig(running);
 
-             // No runners available
 
-             if (config == null) {
 
-                 return null;
 
-             }
 
-             // Create a new runner
 
-             const runner = {
 
-                 config, result: null, didBump: false,
 
-                 perform: null, staller: null
 
-             };
 
-             const now = getTime();
 
-             // Start performing this operation
 
-             runner.perform = (async () => {
 
-                 try {
 
-                     config.requests++;
 
-                     const result = await this._translatePerform(config.provider, req);
 
-                     runner.result = { result };
 
-                 }
 
-                 catch (error) {
 
-                     config.errorResponses++;
 
-                     runner.result = { error };
 
-                 }
 
-                 const dt = (getTime() - now);
 
-                 config._totalTime += dt;
 
-                 config.rollingDuration = 0.95 * config.rollingDuration + 0.05 * dt;
 
-                 runner.perform = null;
 
-             })();
 
-             // Start a staller; when this times out, it's time to force
 
-             // kicking off another runner because we are taking too long
 
-             runner.staller = (async () => {
 
-                 await stall$2(config.stallTimeout);
 
-                 runner.staller = null;
 
-             })();
 
-             running.add(runner);
 
-             return runner;
 
-         }
 
-         // Initializes the blockNumber and network for each runner and
 
-         // blocks until initialized
 
-         async #initialSync() {
 
-             let initialSync = this.#initialSyncPromise;
 
-             if (!initialSync) {
 
-                 const promises = [];
 
-                 this.#configs.forEach((config) => {
 
-                     promises.push((async () => {
 
-                         await waitForSync(config, 0);
 
-                         if (!config._lastFatalError) {
 
-                             config._network = await config.provider.getNetwork();
 
-                         }
 
-                     })());
 
-                 });
 
-                 this.#initialSyncPromise = initialSync = (async () => {
 
-                     // Wait for all providers to have a block number and network
 
-                     await Promise.all(promises);
 
-                     // Check all the networks match
 
-                     let chainId = null;
 
-                     for (const config of this.#configs) {
 
-                         if (config._lastFatalError) {
 
-                             continue;
 
-                         }
 
-                         const network = (config._network);
 
-                         if (chainId == null) {
 
-                             chainId = network.chainId;
 
-                         }
 
-                         else if (network.chainId !== chainId) {
 
-                             assert(false, "cannot mix providers on different networks", "UNSUPPORTED_OPERATION", {
 
-                                 operation: "new FallbackProvider"
 
-                             });
 
-                         }
 
-                     }
 
-                 })();
 
-             }
 
-             await initialSync;
 
-         }
 
-         async #checkQuorum(running, req) {
 
-             // Get all the result objects
 
-             const results = [];
 
-             for (const runner of running) {
 
-                 if (runner.result != null) {
 
-                     const { tag, value } = normalizeResult(runner.result);
 
-                     results.push({ tag, value, weight: runner.config.weight });
 
-                 }
 
-             }
 
-             // Are there enough results to event meet quorum?
 
-             if (results.reduce((a, r) => (a + r.weight), 0) < this.quorum) {
 
-                 return undefined;
 
-             }
 
-             switch (req.method) {
 
-                 case "getBlockNumber": {
 
-                     // We need to get the bootstrap block height
 
-                     if (this.#height === -2) {
 
-                         this.#height = Math.ceil(getNumber(getMedian(this.quorum, this.#configs.filter((c) => (!c._lastFatalError)).map((c) => ({
 
-                             value: c.blockNumber,
 
-                             tag: getNumber(c.blockNumber).toString(),
 
-                             weight: c.weight
 
-                         })))));
 
-                     }
 
-                     // Find the mode across all the providers, allowing for
 
-                     // a little drift between block heights
 
-                     const mode = getFuzzyMode(this.quorum, results);
 
-                     if (mode === undefined) {
 
-                         return undefined;
 
-                     }
 
-                     if (mode > this.#height) {
 
-                         this.#height = mode;
 
-                     }
 
-                     return this.#height;
 
-                 }
 
-                 case "getGasPrice":
 
-                 case "getPriorityFee":
 
-                 case "estimateGas":
 
-                     return getMedian(this.quorum, results);
 
-                 case "getBlock":
 
-                     // Pending blocks are in the mempool and already
 
-                     // quite untrustworthy; just grab anything
 
-                     if ("blockTag" in req && req.blockTag === "pending") {
 
-                         return getAnyResult(this.quorum, results);
 
-                     }
 
-                     return checkQuorum(this.quorum, results);
 
-                 case "call":
 
-                 case "chainId":
 
-                 case "getBalance":
 
-                 case "getTransactionCount":
 
-                 case "getCode":
 
-                 case "getStorage":
 
-                 case "getTransaction":
 
-                 case "getTransactionReceipt":
 
-                 case "getLogs":
 
-                     return checkQuorum(this.quorum, results);
 
-                 case "broadcastTransaction":
 
-                     return getAnyResult(this.quorum, results);
 
-             }
 
-             assert(false, "unsupported method", "UNSUPPORTED_OPERATION", {
 
-                 operation: `_perform(${stringify(req.method)})`
 
-             });
 
-         }
 
-         async #waitForQuorum(running, req) {
 
-             if (running.size === 0) {
 
-                 throw new Error("no runners?!");
 
-             }
 
-             // Any promises that are interesting to watch for; an expired stall
 
-             // or a successful perform
 
-             const interesting = [];
 
-             let newRunners = 0;
 
-             for (const runner of running) {
 
-                 // No responses, yet; keep an eye on it
 
-                 if (runner.perform) {
 
-                     interesting.push(runner.perform);
 
-                 }
 
-                 // Still stalling...
 
-                 if (runner.staller) {
 
-                     interesting.push(runner.staller);
 
-                     continue;
 
-                 }
 
-                 // This runner has already triggered another runner
 
-                 if (runner.didBump) {
 
-                     continue;
 
-                 }
 
-                 // Got a response (result or error) or stalled; kick off another runner
 
-                 runner.didBump = true;
 
-                 newRunners++;
 
-             }
 
-             // Check if we have reached quorum on a result (or error)
 
-             const value = await this.#checkQuorum(running, req);
 
-             if (value !== undefined) {
 
-                 if (value instanceof Error) {
 
-                     throw value;
 
-                 }
 
-                 return value;
 
-             }
 
-             // Add any new runners, because a staller timed out or a result
 
-             // or error response came in.
 
-             for (let i = 0; i < newRunners; i++) {
 
-                 this.#addRunner(running, req);
 
-             }
 
-             // All providers have returned, and we have no result
 
-             assert(interesting.length > 0, "quorum not met", "SERVER_ERROR", {
 
-                 request: "%sub-requests",
 
-                 info: { request: req, results: Array.from(running).map((r) => stringify(r.result)) }
 
-             });
 
-             // Wait for someone to either complete its perform or stall out
 
-             await Promise.race(interesting);
 
-             // This is recursive, but at worst case the depth is 2x the
 
-             // number of providers (each has a perform and a staller)
 
-             return await this.#waitForQuorum(running, req);
 
-         }
 
-         async _perform(req) {
 
-             // Broadcasting a transaction is rare (ish) and already incurs
 
-             // a cost on the user, so spamming is safe-ish. Just send it to
 
-             // every backend.
 
-             if (req.method === "broadcastTransaction") {
 
-                 // Once any broadcast provides a positive result, use it. No
 
-                 // need to wait for anyone else
 
-                 const results = this.#configs.map((c) => null);
 
-                 const broadcasts = this.#configs.map(async ({ provider, weight }, index) => {
 
-                     try {
 
-                         const result = await provider._perform(req);
 
-                         results[index] = Object.assign(normalizeResult({ result }), { weight });
 
-                     }
 
-                     catch (error) {
 
-                         results[index] = Object.assign(normalizeResult({ error }), { weight });
 
-                     }
 
-                 });
 
-                 // As each promise finishes...
 
-                 while (true) {
 
-                     // Check for a valid broadcast result
 
-                     const done = results.filter((r) => (r != null));
 
-                     for (const { value } of done) {
 
-                         if (!(value instanceof Error)) {
 
-                             return value;
 
-                         }
 
-                     }
 
-                     // Check for a legit broadcast error (one which we cannot
 
-                     // recover from; some nodes may return the following red
 
-                     // herring events:
 
-                     // - alredy seend (UNKNOWN_ERROR)
 
-                     // - NONCE_EXPIRED
 
-                     // - REPLACEMENT_UNDERPRICED
 
-                     const result = checkQuorum(this.quorum, results.filter((r) => (r != null)));
 
-                     if (isError(result, "INSUFFICIENT_FUNDS")) {
 
-                         throw result;
 
-                     }
 
-                     // Kick off the next provider (if any)
 
-                     const waiting = broadcasts.filter((b, i) => (results[i] == null));
 
-                     if (waiting.length === 0) {
 
-                         break;
 
-                     }
 
-                     await Promise.race(waiting);
 
-                 }
 
-                 // Use standard quorum results; any result was returned above,
 
-                 // so this will find any error that met quorum if any
 
-                 const result = getAnyResult(this.quorum, results);
 
-                 assert(result !== undefined, "problem multi-broadcasting", "SERVER_ERROR", {
 
-                     request: "%sub-requests",
 
-                     info: { request: req, results: results.map(stringify) }
 
-                 });
 
-                 if (result instanceof Error) {
 
-                     throw result;
 
-                 }
 
-                 return result;
 
-             }
 
-             await this.#initialSync();
 
-             // Bootstrap enough runners to meet quorum
 
-             const running = new Set();
 
-             let inflightQuorum = 0;
 
-             while (true) {
 
-                 const runner = this.#addRunner(running, req);
 
-                 if (runner == null) {
 
-                     break;
 
-                 }
 
-                 inflightQuorum += runner.config.weight;
 
-                 if (inflightQuorum >= this.quorum) {
 
-                     break;
 
-                 }
 
-             }
 
-             const result = await this.#waitForQuorum(running, req);
 
-             // Track requests sent to a provider that are still
 
-             // outstanding after quorum has been otherwise found
 
-             for (const runner of running) {
 
-                 if (runner.perform && runner.result == null) {
 
-                     runner.config.lateResponses++;
 
-                 }
 
-             }
 
-             return result;
 
-         }
 
-         async destroy() {
 
-             for (const { provider } of this.#configs) {
 
-                 provider.destroy();
 
-             }
 
-             super.destroy();
 
-         }
 
-     }
 
-     function isWebSocketLike(value) {
 
-         return (value && typeof (value.send) === "function" &&
 
-             typeof (value.close) === "function");
 
-     }
 
-     const Testnets = "goerli kovan sepolia classicKotti optimism-goerli arbitrum-goerli matic-mumbai bnbt".split(" ");
 
-     /**
 
-      *  Returns a default provider for %%network%%.
 
-      *
 
-      *  If %%network%% is a [[WebSocketLike]] or string that begins with
 
-      *  ``"ws:"`` or ``"wss:"``, a [[WebSocketProvider]] is returned backed
 
-      *  by that WebSocket or URL.
 
-      *
 
-      *  If %%network%% is a string that begins with ``"HTTP:"`` or ``"HTTPS:"``,
 
-      *  a [[JsonRpcProvider]] is returned connected to that URL.
 
-      *
 
-      *  Otherwise, a default provider is created backed by well-known public
 
-      *  Web3 backends (such as [[link-infura]]) using community-provided API
 
-      *  keys.
 
-      *
 
-      *  The %%options%% allows specifying custom API keys per backend (setting
 
-      *  an API key to ``"-"`` will omit that provider) and ``options.exclusive``
 
-      *  can be set to either a backend name or and array of backend names, which
 
-      *  will whitelist **only** those backends.
 
-      *
 
-      *  Current backend strings supported are:
 
-      *  - ``"alchemy"``
 
-      *  - ``"ankr"``
 
-      *  - ``"cloudflare"``
 
-      *  - ``"chainstack"``
 
-      *  - ``"etherscan"``
 
-      *  - ``"infura"``
 
-      *  - ``"publicPolygon"``
 
-      *  - ``"quicknode"``
 
-      *
 
-      *  @example:
 
-      *    // Connect to a local Geth node
 
-      *    provider = getDefaultProvider("http://localhost:8545/");
 
-      *
 
-      *    // Connect to Ethereum mainnet with any current and future
 
-      *    // third-party services available
 
-      *    provider = getDefaultProvider("mainnet");
 
-      *
 
-      *    // Connect to Polygon, but only allow Etherscan and
 
-      *    // INFURA and use "MY_API_KEY" in calls to Etherscan.
 
-      *    provider = getDefaultProvider("matic", {
 
-      *      etherscan: "MY_API_KEY",
 
-      *      exclusive: [ "etherscan", "infura" ]
 
-      *    });
 
-      */
 
-     function getDefaultProvider(network, options) {
 
-         if (options == null) {
 
-             options = {};
 
-         }
 
-         const allowService = (name) => {
 
-             if (options[name] === "-") {
 
-                 return false;
 
-             }
 
-             if (typeof (options.exclusive) === "string") {
 
-                 return (name === options.exclusive);
 
-             }
 
-             if (Array.isArray(options.exclusive)) {
 
-                 return (options.exclusive.indexOf(name) !== -1);
 
-             }
 
-             return true;
 
-         };
 
-         if (typeof (network) === "string" && network.match(/^https?:/)) {
 
-             return new JsonRpcProvider(network);
 
-         }
 
-         if (typeof (network) === "string" && network.match(/^wss?:/) || isWebSocketLike(network)) {
 
-             return new WebSocketProvider(network);
 
-         }
 
-         // Get the network and name, if possible
 
-         let staticNetwork = null;
 
-         try {
 
-             staticNetwork = Network.from(network);
 
-         }
 
-         catch (error) { }
 
-         const providers = [];
 
-         if (allowService("publicPolygon") && staticNetwork) {
 
-             if (staticNetwork.name === "matic") {
 
-                 providers.push(new JsonRpcProvider("https:/\/polygon-rpc.com/", staticNetwork, { staticNetwork }));
 
-             }
 
-             else if (staticNetwork.name === "matic-amoy") {
 
-                 providers.push(new JsonRpcProvider("https:/\/rpc-amoy.polygon.technology/", staticNetwork, { staticNetwork }));
 
-             }
 
-         }
 
-         if (allowService("alchemy")) {
 
-             try {
 
-                 providers.push(new AlchemyProvider(network, options.alchemy));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         if (allowService("ankr") && options.ankr != null) {
 
-             try {
 
-                 providers.push(new AnkrProvider(network, options.ankr));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         if (allowService("chainstack")) {
 
-             try {
 
-                 providers.push(new ChainstackProvider(network, options.chainstack));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         if (allowService("cloudflare")) {
 
-             try {
 
-                 providers.push(new CloudflareProvider(network));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         if (allowService("etherscan")) {
 
-             try {
 
-                 providers.push(new EtherscanProvider(network, options.etherscan));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         if (allowService("infura")) {
 
-             try {
 
-                 let projectId = options.infura;
 
-                 let projectSecret = undefined;
 
-                 if (typeof (projectId) === "object") {
 
-                     projectSecret = projectId.projectSecret;
 
-                     projectId = projectId.projectId;
 
-                 }
 
-                 providers.push(new InfuraProvider(network, projectId, projectSecret));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         /*
 
-             if (options.pocket !== "-") {
 
-                 try {
 
-                     let appId = options.pocket;
 
-                     let secretKey: undefined | string = undefined;
 
-                     let loadBalancer: undefined | boolean = undefined;
 
-                     if (typeof(appId) === "object") {
 
-                         loadBalancer = !!appId.loadBalancer;
 
-                         secretKey = appId.secretKey;
 
-                         appId = appId.appId;
 
-                     }
 
-                     providers.push(new PocketProvider(network, appId, secretKey, loadBalancer));
 
-                 } catch (error) { console.log(error); }
 
-             }
 
-         */
 
-         if (allowService("quicknode")) {
 
-             try {
 
-                 let token = options.quicknode;
 
-                 providers.push(new QuickNodeProvider(network, token));
 
-             }
 
-             catch (error) { }
 
-         }
 
-         assert(providers.length, "unsupported default network", "UNSUPPORTED_OPERATION", {
 
-             operation: "getDefaultProvider"
 
-         });
 
-         // No need for a FallbackProvider
 
-         if (providers.length === 1) {
 
-             return providers[0];
 
-         }
 
-         // We use the floor because public third-party providers can be unreliable,
 
-         // so a low number of providers with a large quorum will fail too often
 
-         let quorum = Math.floor(providers.length / 2);
 
-         if (quorum > 2) {
 
-             quorum = 2;
 
-         }
 
-         // Testnets don't need as strong a security gaurantee and speed is
 
-         // more useful during testing
 
-         if (staticNetwork && Testnets.indexOf(staticNetwork.name) !== -1) {
 
-             quorum = 1;
 
-         }
 
-         // Provided override qorum takes priority
 
-         if (options && options.quorum) {
 
-             quorum = options.quorum;
 
-         }
 
-         return new FallbackProvider(providers, undefined, { quorum });
 
-     }
 
-     /**
 
-      *  A **NonceManager** wraps another [[Signer]] and automatically manages
 
-      *  the nonce, ensuring serialized and sequential nonces are used during
 
-      *  transaction.
 
-      */
 
-     class NonceManager extends AbstractSigner {
 
-         /**
 
-          *  The Signer being managed.
 
-          */
 
-         signer;
 
-         #noncePromise;
 
-         #delta;
 
-         /**
 
-          *  Creates a new **NonceManager** to manage %%signer%%.
 
-          */
 
-         constructor(signer) {
 
-             super(signer.provider);
 
-             defineProperties(this, { signer });
 
-             this.#noncePromise = null;
 
-             this.#delta = 0;
 
-         }
 
-         async getAddress() {
 
-             return this.signer.getAddress();
 
-         }
 
-         connect(provider) {
 
-             return new NonceManager(this.signer.connect(provider));
 
-         }
 
-         async getNonce(blockTag) {
 
-             if (blockTag === "pending") {
 
-                 if (this.#noncePromise == null) {
 
-                     this.#noncePromise = super.getNonce("pending");
 
-                 }
 
-                 const delta = this.#delta;
 
-                 return (await this.#noncePromise) + delta;
 
-             }
 
-             return super.getNonce(blockTag);
 
-         }
 
-         /**
 
-          *  Manually increment the nonce. This may be useful when managng
 
-          *  offline transactions.
 
-          */
 
-         increment() {
 
-             this.#delta++;
 
-         }
 
-         /**
 
-          *  Resets the nonce, causing the **NonceManager** to reload the current
 
-          *  nonce from the blockchain on the next transaction.
 
-          */
 
-         reset() {
 
-             this.#delta = 0;
 
-             this.#noncePromise = null;
 
-         }
 
-         async sendTransaction(tx) {
 
-             const noncePromise = this.getNonce("pending");
 
-             this.increment();
 
-             tx = await this.signer.populateTransaction(tx);
 
-             tx.nonce = await noncePromise;
 
-             // @TODO: Maybe handle interesting/recoverable errors?
 
-             // Like don't increment if the tx was certainly not sent
 
-             return await this.signer.sendTransaction(tx);
 
-         }
 
-         signTransaction(tx) {
 
-             return this.signer.signTransaction(tx);
 
-         }
 
-         signMessage(message) {
 
-             return this.signer.signMessage(message);
 
-         }
 
-         signTypedData(domain, types, value) {
 
-             return this.signer.signTypedData(domain, types, value);
 
-         }
 
-     }
 
-     /**
 
-      *  A **BrowserProvider** is intended to wrap an injected provider which
 
-      *  adheres to the [[link-eip-1193]] standard, which most (if not all)
 
-      *  currently do.
 
-      */
 
-     class BrowserProvider extends JsonRpcApiPollingProvider {
 
-         #request;
 
-         /**
 
-          *  Connect to the %%ethereum%% provider, optionally forcing the
 
-          *  %%network%%.
 
-          */
 
-         constructor(ethereum, network, _options) {
 
-             // Copy the options
 
-             const options = Object.assign({}, ((_options != null) ? _options : {}), { batchMaxCount: 1 });
 
-             assertArgument(ethereum && ethereum.request, "invalid EIP-1193 provider", "ethereum", ethereum);
 
-             super(network, options);
 
-             this.#request = async (method, params) => {
 
-                 const payload = { method, params };
 
-                 this.emit("debug", { action: "sendEip1193Request", payload });
 
-                 try {
 
-                     const result = await ethereum.request(payload);
 
-                     this.emit("debug", { action: "receiveEip1193Result", result });
 
-                     return result;
 
-                 }
 
-                 catch (e) {
 
-                     const error = new Error(e.message);
 
-                     error.code = e.code;
 
-                     error.data = e.data;
 
-                     error.payload = payload;
 
-                     this.emit("debug", { action: "receiveEip1193Error", error });
 
-                     throw error;
 
-                 }
 
-             };
 
-         }
 
-         async send(method, params) {
 
-             await this._start();
 
-             return await super.send(method, params);
 
-         }
 
-         async _send(payload) {
 
-             assertArgument(!Array.isArray(payload), "EIP-1193 does not support batch request", "payload", payload);
 
-             try {
 
-                 const result = await this.#request(payload.method, payload.params || []);
 
-                 return [{ id: payload.id, result }];
 
-             }
 
-             catch (e) {
 
-                 return [{
 
-                         id: payload.id,
 
-                         error: { code: e.code, data: e.data, message: e.message }
 
-                     }];
 
-             }
 
-         }
 
-         getRpcError(payload, error) {
 
-             error = JSON.parse(JSON.stringify(error));
 
-             // EIP-1193 gives us some machine-readable error codes, so rewrite
 
-             // them into 
 
-             switch (error.error.code || -1) {
 
-                 case 4001:
 
-                     error.error.message = `ethers-user-denied: ${error.error.message}`;
 
-                     break;
 
-                 case 4200:
 
-                     error.error.message = `ethers-unsupported: ${error.error.message}`;
 
-                     break;
 
-             }
 
-             return super.getRpcError(payload, error);
 
-         }
 
-         /**
 
-          *  Resolves to ``true`` if the provider manages the %%address%%.
 
-          */
 
-         async hasSigner(address) {
 
-             if (address == null) {
 
-                 address = 0;
 
-             }
 
-             const accounts = await this.send("eth_accounts", []);
 
-             if (typeof (address) === "number") {
 
-                 return (accounts.length > address);
 
-             }
 
-             address = address.toLowerCase();
 
-             return accounts.filter((a) => (a.toLowerCase() === address)).length !== 0;
 
-         }
 
-         async getSigner(address) {
 
-             if (address == null) {
 
-                 address = 0;
 
-             }
 
-             if (!(await this.hasSigner(address))) {
 
-                 try {
 
-                     //const resp = 
 
-                     await this.#request("eth_requestAccounts", []);
 
-                     //console.log("RESP", resp);
 
-                 }
 
-                 catch (error) {
 
-                     const payload = error.payload;
 
-                     throw this.getRpcError(payload, { id: payload.id, error });
 
-                 }
 
-             }
 
-             return await super.getSigner(address);
 
-         }
 
-     }
 
-     /**
 
-      *  [[link-pocket]] provides a third-party service for connecting to
 
-      *  various blockchains over JSON-RPC.
 
-      *
 
-      *  **Supported Networks**
 
-      *
 
-      *  - Ethereum Mainnet (``mainnet``)
 
-      *  - Goerli Testnet (``goerli``)
 
-      *  - Polygon (``matic``)
 
-      *  - Arbitrum (``arbitrum``)
 
-      *
 
-      *  @_subsection: api/providers/thirdparty:Pocket  [providers-pocket]
 
-      */
 
-     const defaultApplicationId = "62e1ad51b37b8e00394bda3b";
 
-     function getHost(name) {
 
-         switch (name) {
 
-             case "mainnet":
 
-                 return "eth-mainnet.gateway.pokt.network";
 
-             case "goerli":
 
-                 return "eth-goerli.gateway.pokt.network";
 
-             case "matic":
 
-                 return "poly-mainnet.gateway.pokt.network";
 
-             case "matic-mumbai":
 
-                 return "polygon-mumbai-rpc.gateway.pokt.network";
 
-         }
 
-         assertArgument(false, "unsupported network", "network", name);
 
-     }
 
-     /**
 
-      *  The **PocketProvider** connects to the [[link-pocket]]
 
-      *  JSON-RPC end-points.
 
-      *
 
-      *  By default, a highly-throttled API key is used, which is
 
-      *  appropriate for quick prototypes and simple scripts. To
 
-      *  gain access to an increased rate-limit, it is highly
 
-      *  recommended to [sign up here](link-pocket-signup).
 
-      */
 
-     class PocketProvider extends JsonRpcProvider {
 
-         /**
 
-          *  The Application ID for the Pocket connection.
 
-          */
 
-         applicationId;
 
-         /**
 
-          *  The Application Secret for making authenticated requests
 
-          *  to the Pocket connection.
 
-          */
 
-         applicationSecret;
 
-         /**
 
-          *  Create a new **PocketProvider**.
 
-          *
 
-          *  By default connecting to ``mainnet`` with a highly throttled
 
-          *  API key.
 
-          */
 
-         constructor(_network, applicationId, applicationSecret) {
 
-             if (_network == null) {
 
-                 _network = "mainnet";
 
-             }
 
-             const network = Network.from(_network);
 
-             if (applicationId == null) {
 
-                 applicationId = defaultApplicationId;
 
-             }
 
-             if (applicationSecret == null) {
 
-                 applicationSecret = null;
 
-             }
 
-             const options = { staticNetwork: network };
 
-             const request = PocketProvider.getRequest(network, applicationId, applicationSecret);
 
-             super(request, network, options);
 
-             defineProperties(this, { applicationId, applicationSecret });
 
-         }
 
-         _getProvider(chainId) {
 
-             try {
 
-                 return new PocketProvider(chainId, this.applicationId, this.applicationSecret);
 
-             }
 
-             catch (error) { }
 
-             return super._getProvider(chainId);
 
-         }
 
-         /**
 
-          *  Returns a prepared request for connecting to %%network%% with
 
-          *  %%applicationId%%.
 
-          */
 
-         static getRequest(network, applicationId, applicationSecret) {
 
-             if (applicationId == null) {
 
-                 applicationId = defaultApplicationId;
 
-             }
 
-             const request = new FetchRequest(`https:/\/${getHost(network.name)}/v1/lb/${applicationId}`);
 
-             request.allowGzip = true;
 
-             if (applicationSecret) {
 
-                 request.setCredentials("", applicationSecret);
 
-             }
 
-             if (applicationId === defaultApplicationId) {
 
-                 request.retryFunc = async (request, response, attempt) => {
 
-                     showThrottleMessage("PocketProvider");
 
-                     return true;
 
-                 };
 
-             }
 
-             return request;
 
-         }
 
-         isCommunityResource() {
 
-             return (this.applicationId === defaultApplicationId);
 
-         }
 
-     }
 
-     const IpcSocketProvider = undefined;
 
-     /**
 
-      *  The **BaseWallet** is a stream-lined implementation of a
 
-      *  [[Signer]] that operates with a private key.
 
-      *
 
-      *  It is preferred to use the [[Wallet]] class, as it offers
 
-      *  additional functionality and simplifies loading a variety
 
-      *  of JSON formats, Mnemonic Phrases, etc.
 
-      *
 
-      *  This class may be of use for those attempting to implement
 
-      *  a minimal Signer.
 
-      */
 
-     class BaseWallet extends AbstractSigner {
 
-         /**
 
-          *  The wallet address.
 
-          */
 
-         address;
 
-         #signingKey;
 
-         /**
 
-          *  Creates a new BaseWallet for %%privateKey%%, optionally
 
-          *  connected to %%provider%%.
 
-          *
 
-          *  If %%provider%% is not specified, only offline methods can
 
-          *  be used.
 
-          */
 
-         constructor(privateKey, provider) {
 
-             super(provider);
 
-             assertArgument(privateKey && typeof (privateKey.sign) === "function", "invalid private key", "privateKey", "[ REDACTED ]");
 
-             this.#signingKey = privateKey;
 
-             const address = computeAddress(this.signingKey.publicKey);
 
-             defineProperties(this, { address });
 
-         }
 
-         // Store private values behind getters to reduce visibility
 
-         // in console.log
 
-         /**
 
-          *  The [[SigningKey]] used for signing payloads.
 
-          */
 
-         get signingKey() { return this.#signingKey; }
 
-         /**
 
-          *  The private key for this wallet.
 
-          */
 
-         get privateKey() { return this.signingKey.privateKey; }
 
-         async getAddress() { return this.address; }
 
-         connect(provider) {
 
-             return new BaseWallet(this.#signingKey, provider);
 
-         }
 
-         async signTransaction(tx) {
 
-             tx = copyRequest(tx);
 
-             // Replace any Addressable or ENS name with an address
 
-             const { to, from } = await resolveProperties({
 
-                 to: (tx.to ? resolveAddress(tx.to, this.provider) : undefined),
 
-                 from: (tx.from ? resolveAddress(tx.from, this.provider) : undefined)
 
-             });
 
-             if (to != null) {
 
-                 tx.to = to;
 
-             }
 
-             if (from != null) {
 
-                 tx.from = from;
 
-             }
 
-             if (tx.from != null) {
 
-                 assertArgument(getAddress((tx.from)) === this.address, "transaction from address mismatch", "tx.from", tx.from);
 
-                 delete tx.from;
 
-             }
 
-             // Build the transaction
 
-             const btx = Transaction.from(tx);
 
-             btx.signature = this.signingKey.sign(btx.unsignedHash);
 
-             return btx.serialized;
 
-         }
 
-         async signMessage(message) {
 
-             return this.signMessageSync(message);
 
-         }
 
-         // @TODO: Add a secialized signTx and signTyped sync that enforces
 
-         // all parameters are known?
 
-         /**
 
-          *  Returns the signature for %%message%% signed with this wallet.
 
-          */
 
-         signMessageSync(message) {
 
-             return this.signingKey.sign(hashMessage(message)).serialized;
 
-         }
 
-         async signTypedData(domain, types, value) {
 
-             // Populate any ENS names
 
-             const populated = await TypedDataEncoder.resolveNames(domain, types, value, async (name) => {
 
-                 // @TODO: this should use resolveName; addresses don't
 
-                 //        need a provider
 
-                 assert(this.provider != null, "cannot resolve ENS names without a provider", "UNSUPPORTED_OPERATION", {
 
-                     operation: "resolveName",
 
-                     info: { name }
 
-                 });
 
-                 const address = await this.provider.resolveName(name);
 
-                 assert(address != null, "unconfigured ENS name", "UNCONFIGURED_NAME", {
 
-                     value: name
 
-                 });
 
-                 return address;
 
-             });
 
-             return this.signingKey.sign(TypedDataEncoder.hash(populated.domain, types, populated.value)).serialized;
 
-         }
 
-     }
 
-     const subsChrs = " !#$%&'()*+,-./<=>?@[]^_`{|}~";
 
-     const Word = /^[a-z]*$/i;
 
-     function unfold(words, sep) {
 
-         let initial = 97;
 
-         return words.reduce((accum, word) => {
 
-             if (word === sep) {
 
-                 initial++;
 
-             }
 
-             else if (word.match(Word)) {
 
-                 accum.push(String.fromCharCode(initial) + word);
 
-             }
 
-             else {
 
-                 initial = 97;
 
-                 accum.push(word);
 
-             }
 
-             return accum;
 
-         }, []);
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     function decode(data, subs) {
 
-         // Replace all the substitutions with their expanded form
 
-         for (let i = subsChrs.length - 1; i >= 0; i--) {
 
-             data = data.split(subsChrs[i]).join(subs.substring(2 * i, 2 * i + 2));
 
-         }
 
-         // Get all tle clumps; each suffix, first-increment and second-increment
 
-         const clumps = [];
 
-         const leftover = data.replace(/(:|([0-9])|([A-Z][a-z]*))/g, (all, item, semi, word) => {
 
-             if (semi) {
 
-                 for (let i = parseInt(semi); i >= 0; i--) {
 
-                     clumps.push(";");
 
-                 }
 
-             }
 
-             else {
 
-                 clumps.push(item.toLowerCase());
 
-             }
 
-             return "";
 
-         });
 
-         /* c8 ignore start */
 
-         if (leftover) {
 
-             throw new Error(`leftovers: ${JSON.stringify(leftover)}`);
 
-         }
 
-         /* c8 ignore stop */
 
-         return unfold(unfold(clumps, ";"), ":");
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     function decodeOwl(data) {
 
-         assertArgument(data[0] === "0", "unsupported auwl data", "data", data);
 
-         return decode(data.substring(1 + 2 * subsChrs.length), data.substring(1, 1 + 2 * subsChrs.length));
 
-     }
 
-     /**
 
-      *  A Wordlist represents a collection of language-specific
 
-      *  words used to encode and devoce [[link-bip-39]] encoded data
 
-      *  by mapping words to 11-bit values and vice versa.
 
-      */
 
-     class Wordlist {
 
-         locale;
 
-         /**
 
-          *  Creates a new Wordlist instance.
 
-          *
 
-          *  Sub-classes MUST call this if they provide their own constructor,
 
-          *  passing in the locale string of the language.
 
-          *
 
-          *  Generally there is no need to create instances of a Wordlist,
 
-          *  since each language-specific Wordlist creates an instance and
 
-          *  there is no state kept internally, so they are safe to share.
 
-          */
 
-         constructor(locale) {
 
-             defineProperties(this, { locale });
 
-         }
 
-         /**
 
-          *  Sub-classes may override this to provide a language-specific
 
-          *  method for spliting %%phrase%% into individual words.
 
-          *
 
-          *  By default, %%phrase%% is split using any sequences of
 
-          *  white-space as defined by regular expressions (i.e. ``/\s+/``).
 
-          */
 
-         split(phrase) {
 
-             return phrase.toLowerCase().split(/\s+/g);
 
-         }
 
-         /**
 
-          *  Sub-classes may override this to provider a language-specific
 
-          *  method for joining %%words%% into a phrase.
 
-          *
 
-          *  By default, %%words%% are joined by a single space.
 
-          */
 
-         join(words) {
 
-             return words.join(" ");
 
-         }
 
-     }
 
-     // Use the encode-latin.js script to create the necessary
 
-     // data files to be consumed by this class
 
-     /**
 
-      *  An OWL format Wordlist is an encoding method that exploits
 
-      *  the general locality of alphabetically sorted words to
 
-      *  achieve a simple but effective means of compression.
 
-      *
 
-      *  This class is generally not useful to most developers as
 
-      *  it is used mainly internally to keep Wordlists for languages
 
-      *  based on ASCII-7 small.
 
-      *
 
-      *  If necessary, there are tools within the ``generation/`` folder
 
-      *  to create the necessary data.
 
-      */
 
-     class WordlistOwl extends Wordlist {
 
-         #data;
 
-         #checksum;
 
-         /**
 
-          *  Creates a new Wordlist for %%locale%% using the OWL %%data%%
 
-          *  and validated against the %%checksum%%.
 
-          */
 
-         constructor(locale, data, checksum) {
 
-             super(locale);
 
-             this.#data = data;
 
-             this.#checksum = checksum;
 
-             this.#words = null;
 
-         }
 
-         /**
 
-          *  The OWL-encoded data.
 
-          */
 
-         get _data() { return this.#data; }
 
-         /**
 
-          *  Decode all the words for the wordlist.
 
-          */
 
-         _decodeWords() {
 
-             return decodeOwl(this.#data);
 
-         }
 
-         #words;
 
-         #loadWords() {
 
-             if (this.#words == null) {
 
-                 const words = this._decodeWords();
 
-                 // Verify the computed list matches the official list
 
-                 const checksum = id(words.join("\n") + "\n");
 
-                 /* c8 ignore start */
 
-                 if (checksum !== this.#checksum) {
 
-                     throw new Error(`BIP39 Wordlist for ${this.locale} FAILED`);
 
-                 }
 
-                 /* c8 ignore stop */
 
-                 this.#words = words;
 
-             }
 
-             return this.#words;
 
-         }
 
-         getWord(index) {
 
-             const words = this.#loadWords();
 
-             assertArgument(index >= 0 && index < words.length, `invalid word index: ${index}`, "index", index);
 
-             return words[index];
 
-         }
 
-         getWordIndex(word) {
 
-             return this.#loadWords().indexOf(word);
 
-         }
 
-     }
 
-     const words = "0erleonalorenseinceregesticitStanvetearctssi#ch2Athck&tneLl0And#Il.yLeOutO=S|S%b/ra@SurdU'0Ce[Cid|CountCu'Hie=IdOu,-Qui*Ro[TT]T%T*[Tu$0AptDD-tD*[Ju,M.UltV<)Vi)0Rob-0FairF%dRaid0A(EEntRee0Ead0MRRp%tS!_rmBumCoholErtI&LLeyLowMo,O}PhaReadySoT Ways0A>urAz(gOngOuntU'd0Aly,Ch%Ci|G G!GryIm$K!Noun)Nu$O` Sw T&naTiqueXietyY1ArtOlogyPe?P!Pro=Ril1ChCt-EaEnaGueMMedM%MyOundR<+Re,Ri=RowTTefa@Ti,Tw%k0KPe@SaultSetSi,SumeThma0H!>OmTa{T&dT.udeTra@0Ct]D.Gu,NtTh%ToTumn0Era+OcadoOid0AkeA*AyEsomeFulKw?d0Is:ByChel%C#D+GL<)Lc#y~MbooN<aNn RRelyRga(R*lSeS-SketTt!3A^AnAutyCau'ComeEfF%eG(Ha=H(dLie=LowLtN^Nef./TrayTt Twe&Y#d3Cyc!DKeNdOlogyRdR`Tt _{AdeAmeAnketA,EakE[IndOodO[omOu'UeUrUsh_rdAtDyIlMbNeNusOkO,Rd R(gRrowSsTtomUn)XY_{etA(AndA[A=EadEezeI{Id+IefIghtIngIskOccoliOk&OnzeOomO` OwnUsh2Bb!DdyD+tFf$oIldLbLkL!tNd!Nk Rd&Rg R,SS(e[SyTt Y Zz:Bba+B(B!CtusGeKe~LmM aMpNN$N)lNdyNn#NoeNvasNy#Pab!P.$Pta(RRb#RdRgoRpetRryRtSeShS(o/!Su$TT$ogT^Teg%yTt!UghtU'Ut]Ve3Il(gL yM|NsusNturyRe$Rta(_irAlkAmp]An+AosApt Ar+A'AtEapE{Ee'EfErryE,I{&IefIldIm}yOi)Oo'R#-U{!UnkUrn0G?Nnam#Rc!Tiz&TyVil_imApArifyAwAyE<ErkEv I{I|IffImbIn-IpO{OgO'O`OudOwnUbUmpU, Ut^_^A,C#utDeFfeeIlInL!@L%LumnMb(eMeMf%tM-Mm#Mp<yNc tNdu@NfirmNg*[N}@Nsid NtrolNv()OkOlPp PyR$ReRnR*@/Tt#U^UntryUp!Ur'Us(V Yo>_{Ad!AftAmA}AshAt AwlAzyEamEd.EekEwI{etImeIspIt-OpO[Ou^OwdUci$UelUi'Umb!Un^UshYY,$2BeLtu*PPbo?dRiousRr|Rta(R=Sh]/omTe3C!:DMa+MpN)Ng R(gShUght WnY3AlBa>BrisCadeCemb CideCl(eC%a>C*a'ErF&'F(eFyG*eLayLiv M<dMi'Ni$Nti,NyP?tP&dPos.P`PutyRi=ScribeS tSignSkSpair/royTailTe@VelopVi)Vo>3AgramAlAm#dAryCeE'lEtFf G.$Gn.yLemmaNn NosaurRe@RtSag*eScov Sea'ShSmi[S%d Splay/<)V tVideV%)Zzy5Ct%Cum|G~Lph(Ma(Na>NkeyN%OrSeUb!Ve_ftAg#AmaA,-AwEamE[IftIllInkIpI=OpUmY2CkMbNeR(g/T^Ty1Arf1Nam-:G G!RlyRnR`Sily/Sy1HoOlogyOnomy0GeItUca>1F%t0G1GhtTh 2BowD E@r-Eg<tEm|Eph<tEvat%I>Se0B?kBodyBra)Er+Ot]PloyPow Pty0Ab!A@DD![D%'EmyErgyF%)Ga+G(eH<)JoyLi,OughR-hRollSu*T Ti*TryVelope1Isode0U$Uip0AA'OdeOs]R%Upt0CapeSayS&)Ta>0Ern$H-s1Id&)IlOkeOl=1A@Amp!Ce[Ch<+C.eCludeCu'Ecu>Erci'Hau,Hib.I!I,ItOt-P<dPe@Pi*Pla(Po'P*[T&dTra0EEbrow:Br-CeCultyDeIntI`~L'MeMilyMousNNcyNtasyRmSh]TT$Th TigueUltV%.e3Atu*Bru?yD $EEdElMa!N)/iv$T^V W3B Ct]EldGu*LeLmLt N$NdNeNg NishReRmR,Sc$ShTT}[X_gAmeAshAtAv%EeIghtIpOatO{O%Ow UidUshY_mCusGIlLd~owOdOtR)Re,R+tRkRtu}RumRw?dSsil/ UndX_gi!AmeEqu|EshI&dIn+OgOntO,OwnOz&U.2ElNNnyRna)RyTu*:D+tInLaxy~ yMePRa+Rba+Rd&Rl-Rm|SSpTeTh U+Ze3N $NiusN*Nt!Nu(e/u*2O,0AntFtGg!Ng RaffeRlVe_dAn)A*A[IdeImp'ObeOomOryO=OwUe_tDde[LdOdO'RillaSpelSsipV nWn_bA)A(AntApeA[Av.yEatE&IdIefItOc yOupOwUnt_rdE[IdeIltIt?N3M:B.IrLfMm M, NdPpyRb%RdRshR=,TVeWkZ?d3AdAl`ArtAvyD+hogIght~oLmetLpNRo3Dd&Gh~NtPRe/%y5BbyCkeyLdLeLiday~owMeNeyOdPeRnRr%R'Sp.$/TelUrV 5BGeM<Mb!M%Nd*dNgryNtRd!RryRtSb<d3Brid:1EOn0EaEntifyLe2N%e4LLeg$L}[0A+Ita>M&'Mu}Pa@Po'Pro=Pul'0ChCludeComeC*a'DexD-a>Do%Du,ryF<tFl-tF%mHa!H .Iti$Je@JuryMa>N Noc|PutQuiryS<eSe@SideSpi*/$lTa@T e,ToVe,V.eVol=3On0L<dOla>Sue0Em1Ory:CketGu?RZz3AlousAns~yWel9BInKeUr}yY5D+I)MpNg!Ni%Nk/:Ng?oo3EnEpT^upY3CkDD}yNdNgdomSsTT^&TeTt&Wi4EeIfeO{Ow:BBelB%Dd DyKeMpNgua+PtopR+T T(UghUndryVaWWnWsu.Y Zy3Ad AfArnA=Ctu*FtGG$G&dIsu*M#NdNg`NsOp?dSs#Tt Vel3ArB tyBr?yC&'FeFtGhtKeMbM.NkOnQuid/Tt!VeZ?d5AdAnB, C$CkG-NelyNgOpTt yUdUn+VeY$5CkyGga+Mb N?N^Xury3R-s:Ch(eDG-G}tIdIlInJ%KeMm$NNa+Nda>NgoNs]Nu$P!Rb!R^Rg(R(eRketRria+SkSs/ T^T i$ThTrixTt XimumZe3AdowAnAsu*AtCh<-D$DiaLodyLtMb M%yNt]NuRcyR+R.RryShSsa+T$Thod3Dd!DnightLk~]M-NdNimumN%Nu>Rac!Rr%S ySs/akeXXedXtu*5Bi!DelDifyMM|N.%NkeyN, N`OnR$ReRn(gSqu.oTh T]T%Unta(U'VeVie5ChFf(LeLtiplySc!SeumShroomS-/Tu$3Self/ yTh:I=MePk(Rrow/yT]Tu*3ArCkEdGati=G!@I` PhewR=/TTw%kUtr$V WsXt3CeGht5B!I'M(eeOd!Rm$R`SeTab!TeTh(gTi)VelW5C!?Mb R'T:K0EyJe@Li+Scu*S =Ta(Vious0CurE<Tob 0Or1FF Fi)T&2L1Ay0DI=Ymp-0It0CeEI#L(eLy1EnEraIn]Po'T]1An+B.Ch?dD D(?yG<I|Ig($Ph<0Tr-h0H 0Tdo%T TputTside0AlEnEr0NN 0Yg&0/ 0O}:CtDd!GeIrLa)LmNdaNelN-N` P RadeR|RkRrotRtySsT^ThTi|TrolTt nU'VeYm|3A)AnutArAs<tL-<NN$tyNcilOp!Pp Rfe@Rm.Rs#T2O}OtoRa'Ys-$0AnoCn-Ctu*E)GGe#~LotNkO} Pe/olT^Zza_)A}tA,-A>AyEa'Ed+U{UgUn+2EmEtIntL?LeLi)NdNyOlPul?Rt]S.]Ssib!/TatoTt yV tyWd W _@i)Ai'Ed-tEf Epa*Es|EttyEv|I)IdeIm?yIntI%.yIs#Iva>IzeOb!mO)[Odu)Of.OgramOje@Omo>OofOp tyOsp O>@OudOvide2Bl-Dd(g~LpL'Mpk(N^PilPpyR^a'R.yRpo'R'ShTZz!3Ramid:99Al.yAntumArt E,]I{ItIzO>:Bb.Cco#CeCkD?DioIlInI'~yMpN^NdomN+PidReTeTh V&WZ%3AdyAlAs#BelBuildC$lCei=CipeC%dCyc!Du)F!@F%mFu'G]G*tGul?Je@LaxLea'LiefLyMa(Memb M(dMo=Nd NewNtOp&PairPeatPla)P%tQui*ScueSemb!Si,Sour)Sp#'SultTi*T*atTurnUn]Ve$ViewW?d2Y`m0BBb#CeChDeD+F!GhtGidNgOtPp!SkTu$V$V 5AdA,BotBu,CketM<)OfOkieOmSeTa>UghUndU>Y$5Bb DeGLeNNwayR$:DDd!D}[FeIlLadLm#L#LtLu>MeMp!NdTisfyToshiU)Usa+VeY1A!AnA*Att E}HemeHoolI&)I[%sOrp]OutRapRe&RiptRub1AAr^As#AtC#dC*tCt]Cur.yEdEkGm|Le@~M(?Ni%N'Nt&)RiesRvi)Ss]Tt!TupV&_dowAftAllowA*EdEllEriffIeldIftI}IpIv O{OeOotOpOrtOuld O=RimpRugUff!Y0Bl(gCkDeE+GhtGnL|Lk~yLv Mil?Mp!N)NgR&/ Tua>XZe1A>Et^IIllInIrtUll0AbAmEepEnd I)IdeIghtImOg<OtOwUsh0AllArtI!OkeOo`0A{AkeApIffOw0ApCc Ci$CkDaFtL?Ldi LidLut]L=Me#eNgOnRryRtUlUndUpUr)U`0A)A*Ati$AwnEakEci$EedEllEndH eI)Id IkeInIr.L.OilOns%O#OrtOtRayReadR(gY0Ua*UeezeUir*l_b!AdiumAffA+AirsAmpAndArtA>AyEakEelEmEpE*oI{IllIngO{Oma^O}OolOryO=Ra>gyReetRikeR#gRugg!Ud|UffUmb!Y!0Bje@Bm.BwayC)[ChDd&Ff G?G+,ItMm NNnyN'tP PplyP*meReRfa)R+Rpri'RroundR=ySpe@/a(1AllowAmpApArmE?EetIftImIngIt^Ord1MbolMptomRup/em:B!Ck!GIlL|LkNkPeR+tSk/eTtooXi3A^Am~NN<tNnisNtRm/Xt_nkAtEmeEnE%yE*EyIngIsOughtReeRi=RowUmbUnd 0CketDeG LtMb MeNyPRedSsueT!5A,BaccoDayDdl EGe` I!tK&MatoM%rowNeNgueNightOlO`PP-Pp!R^RnadoRtoi'SsT$Uri,W?dW WnY_{AdeAff-Ag-A(Ansf ApAshA=lAyEatEeEndI$IbeI{Igg ImIpOphyOub!U{UeUlyUmpetU,U`Y2BeIt]Mb!NaN}lRkeyRnRt!1El=EntyI)InI,O1PeP-$:5Ly5B*lla0Ab!Awa*C!Cov D DoFairFoldHappyIf%mIqueItIv 'KnownLo{TilUsu$Veil1Da>GradeHoldOnP Set1B<Ge0A+EEdEfulE![U$0Il.y:C<tCuumGueLidL!yL=NNishP%Rious/Ult3H-!L=tNd%Ntu*NueRbRifyRs]RyS'lT <3Ab!Br<tCiousCt%yDeoEw~a+Nta+Ol(Rtu$RusSaS.Su$T$Vid5C$I)IdLc<oLumeTeYa+:GeG#ItLk~LnutNtRfa*RmRri%ShSp/eT VeY3Al`Ap#ArA'lA` BDd(gEk&dIrdLcome/T_!AtEatEelEnE*IpIsp 0DeD`FeLd~NNdowNeNgNkNn Nt ReSdomSeShT}[5LfM<Nd OdOlRdRkRldRryR`_pE{E,!I,I>Ong::Rd3Ar~ow9UUngU`:3BraRo9NeO";
 
-     const checksum = "0x3c8acc1e7b08d8e76f9fda015ef48dc8c710a73cb7e0f77b2c18a9b5a7adde60";
 
-     let wordlist = null;
 
-     /**
 
-      *  The [[link-bip39-en]] for [mnemonic phrases](link-bip-39).
 
-      *
 
-      *  @_docloc: api/wordlists
 
-      */
 
-     class LangEn extends WordlistOwl {
 
-         /**
 
-          *  Creates a new instance of the English language Wordlist.
 
-          *
 
-          *  This should be unnecessary most of the time as the exported
 
-          *  [[langEn]] should suffice.
 
-          *
 
-          *  @_ignore:
 
-          */
 
-         constructor() { super("en", words, checksum); }
 
-         /**
 
-          *  Returns a singleton instance of a ``LangEn``, creating it
 
-          *  if this is the first time being called.
 
-          */
 
-         static wordlist() {
 
-             if (wordlist == null) {
 
-                 wordlist = new LangEn();
 
-             }
 
-             return wordlist;
 
-         }
 
-     }
 
-     // Returns a byte with the MSB bits set
 
-     function getUpperMask(bits) {
 
-         return ((1 << bits) - 1) << (8 - bits) & 0xff;
 
-     }
 
-     // Returns a byte with the LSB bits set
 
-     function getLowerMask(bits) {
 
-         return ((1 << bits) - 1) & 0xff;
 
-     }
 
-     function mnemonicToEntropy(mnemonic, wordlist) {
 
-         assertNormalize("NFKD");
 
-         if (wordlist == null) {
 
-             wordlist = LangEn.wordlist();
 
-         }
 
-         const words = wordlist.split(mnemonic);
 
-         assertArgument((words.length % 3) === 0 && words.length >= 12 && words.length <= 24, "invalid mnemonic length", "mnemonic", "[ REDACTED ]");
 
-         const entropy = new Uint8Array(Math.ceil(11 * words.length / 8));
 
-         let offset = 0;
 
-         for (let i = 0; i < words.length; i++) {
 
-             let index = wordlist.getWordIndex(words[i].normalize("NFKD"));
 
-             assertArgument(index >= 0, `invalid mnemonic word at index ${i}`, "mnemonic", "[ REDACTED ]");
 
-             for (let bit = 0; bit < 11; bit++) {
 
-                 if (index & (1 << (10 - bit))) {
 
-                     entropy[offset >> 3] |= (1 << (7 - (offset % 8)));
 
-                 }
 
-                 offset++;
 
-             }
 
-         }
 
-         const entropyBits = 32 * words.length / 3;
 
-         const checksumBits = words.length / 3;
 
-         const checksumMask = getUpperMask(checksumBits);
 
-         const checksum = getBytes(sha256(entropy.slice(0, entropyBits / 8)))[0] & checksumMask;
 
-         assertArgument(checksum === (entropy[entropy.length - 1] & checksumMask), "invalid mnemonic checksum", "mnemonic", "[ REDACTED ]");
 
-         return hexlify(entropy.slice(0, entropyBits / 8));
 
-     }
 
-     function entropyToMnemonic(entropy, wordlist) {
 
-         assertArgument((entropy.length % 4) === 0 && entropy.length >= 16 && entropy.length <= 32, "invalid entropy size", "entropy", "[ REDACTED ]");
 
-         if (wordlist == null) {
 
-             wordlist = LangEn.wordlist();
 
-         }
 
-         const indices = [0];
 
-         let remainingBits = 11;
 
-         for (let i = 0; i < entropy.length; i++) {
 
-             // Consume the whole byte (with still more to go)
 
-             if (remainingBits > 8) {
 
-                 indices[indices.length - 1] <<= 8;
 
-                 indices[indices.length - 1] |= entropy[i];
 
-                 remainingBits -= 8;
 
-                 // This byte will complete an 11-bit index
 
-             }
 
-             else {
 
-                 indices[indices.length - 1] <<= remainingBits;
 
-                 indices[indices.length - 1] |= entropy[i] >> (8 - remainingBits);
 
-                 // Start the next word
 
-                 indices.push(entropy[i] & getLowerMask(8 - remainingBits));
 
-                 remainingBits += 3;
 
-             }
 
-         }
 
-         // Compute the checksum bits
 
-         const checksumBits = entropy.length / 4;
 
-         const checksum = parseInt(sha256(entropy).substring(2, 4), 16) & getUpperMask(checksumBits);
 
-         // Shift the checksum into the word indices
 
-         indices[indices.length - 1] <<= checksumBits;
 
-         indices[indices.length - 1] |= (checksum >> (8 - checksumBits));
 
-         return wordlist.join(indices.map((index) => wordlist.getWord(index)));
 
-     }
 
-     const _guard$1 = {};
 
-     /**
 
-      *  A **Mnemonic** wraps all properties required to compute [[link-bip-39]]
 
-      *  seeds and convert between phrases and entropy.
 
-      */
 
-     class Mnemonic {
 
-         /**
 
-          *  The mnemonic phrase of 12, 15, 18, 21 or 24 words.
 
-          *
 
-          *  Use the [[wordlist]] ``split`` method to get the individual words.
 
-          */
 
-         phrase;
 
-         /**
 
-          *  The password used for this mnemonic. If no password is used this
 
-          *  is the empty string (i.e. ``""``) as per the specification.
 
-          */
 
-         password;
 
-         /**
 
-          *  The wordlist for this mnemonic.
 
-          */
 
-         wordlist;
 
-         /**
 
-          *  The underlying entropy which the mnemonic encodes.
 
-          */
 
-         entropy;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, entropy, phrase, password, wordlist) {
 
-             if (password == null) {
 
-                 password = "";
 
-             }
 
-             if (wordlist == null) {
 
-                 wordlist = LangEn.wordlist();
 
-             }
 
-             assertPrivate(guard, _guard$1, "Mnemonic");
 
-             defineProperties(this, { phrase, password, wordlist, entropy });
 
-         }
 
-         /**
 
-          *  Returns the seed for the mnemonic.
 
-          */
 
-         computeSeed() {
 
-             const salt = toUtf8Bytes("mnemonic" + this.password, "NFKD");
 
-             return pbkdf2(toUtf8Bytes(this.phrase, "NFKD"), salt, 2048, 64, "sha512");
 
-         }
 
-         /**
 
-          *  Creates a new Mnemonic for the %%phrase%%.
 
-          *
 
-          *  The default %%password%% is the empty string and the default
 
-          *  wordlist is the [English wordlists](LangEn).
 
-          */
 
-         static fromPhrase(phrase, password, wordlist) {
 
-             // Normalize the case and space; throws if invalid
 
-             const entropy = mnemonicToEntropy(phrase, wordlist);
 
-             phrase = entropyToMnemonic(getBytes(entropy), wordlist);
 
-             return new Mnemonic(_guard$1, entropy, phrase, password, wordlist);
 
-         }
 
-         /**
 
-          *  Create a new **Mnemonic** from the %%entropy%%.
 
-          *
 
-          *  The default %%password%% is the empty string and the default
 
-          *  wordlist is the [English wordlists](LangEn).
 
-          */
 
-         static fromEntropy(_entropy, password, wordlist) {
 
-             const entropy = getBytes(_entropy, "entropy");
 
-             const phrase = entropyToMnemonic(entropy, wordlist);
 
-             return new Mnemonic(_guard$1, hexlify(entropy), phrase, password, wordlist);
 
-         }
 
-         /**
 
-          *  Returns the phrase for %%mnemonic%%.
 
-          */
 
-         static entropyToPhrase(_entropy, wordlist) {
 
-             const entropy = getBytes(_entropy, "entropy");
 
-             return entropyToMnemonic(entropy, wordlist);
 
-         }
 
-         /**
 
-          *  Returns the entropy for %%phrase%%.
 
-          */
 
-         static phraseToEntropy(phrase, wordlist) {
 
-             return mnemonicToEntropy(phrase, wordlist);
 
-         }
 
-         /**
 
-          *  Returns true if %%phrase%% is a valid [[link-bip-39]] phrase.
 
-          *
 
-          *  This checks all the provided words belong to the %%wordlist%%,
 
-          *  that the length is valid and the checksum is correct.
 
-          */
 
-         static isValidMnemonic(phrase, wordlist) {
 
-             try {
 
-                 mnemonicToEntropy(phrase, wordlist);
 
-                 return true;
 
-             }
 
-             catch (error) { }
 
-             return false;
 
-         }
 
-     }
 
-     /*! MIT License. Copyright 2015-2022 Richard Moore <me@ricmoo.com>. See LICENSE.txt. */
 
-     var __classPrivateFieldGet$2 = (__$G && __$G.__classPrivateFieldGet) || function (receiver, state, kind, f) {
 
-         if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
 
-         if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
 
-         return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
 
-     };
 
-     var __classPrivateFieldSet$2 = (__$G && __$G.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
 
-         if (kind === "m") throw new TypeError("Private method is not writable");
 
-         if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
 
-         if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
 
-         return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
 
-     };
 
-     var _AES_key, _AES_Kd, _AES_Ke;
 
-     // Number of rounds by keysize
 
-     const numberOfRounds = { 16: 10, 24: 12, 32: 14 };
 
-     // Round constant words
 
-     const rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91];
 
-     // S-box and Inverse S-box (S is for Substitution)
 
-     const S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16];
 
-     const Si = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d];
 
-     // Transformations for encryption
 
-     const T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a];
 
-     const T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616];
 
-     const T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16];
 
-     const T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c];
 
-     // Transformations for decryption
 
-     const T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742];
 
-     const T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857];
 
-     const T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8];
 
-     const T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0];
 
-     // Transformations for decryption key expansion
 
-     const U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3];
 
-     const U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697];
 
-     const U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46];
 
-     const U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d];
 
-     function convertToInt32(bytes) {
 
-         const result = [];
 
-         for (let i = 0; i < bytes.length; i += 4) {
 
-             result.push((bytes[i] << 24) | (bytes[i + 1] << 16) | (bytes[i + 2] << 8) | bytes[i + 3]);
 
-         }
 
-         return result;
 
-     }
 
-     class AES {
 
-         get key() { return __classPrivateFieldGet$2(this, _AES_key, "f").slice(); }
 
-         constructor(key) {
 
-             _AES_key.set(this, void 0);
 
-             _AES_Kd.set(this, void 0);
 
-             _AES_Ke.set(this, void 0);
 
-             if (!(this instanceof AES)) {
 
-                 throw Error('AES must be instanitated with `new`');
 
-             }
 
-             __classPrivateFieldSet$2(this, _AES_key, new Uint8Array(key), "f");
 
-             const rounds = numberOfRounds[this.key.length];
 
-             if (rounds == null) {
 
-                 throw new TypeError('invalid key size (must be 16, 24 or 32 bytes)');
 
-             }
 
-             // encryption round keys
 
-             __classPrivateFieldSet$2(this, _AES_Ke, [], "f");
 
-             // decryption round keys
 
-             __classPrivateFieldSet$2(this, _AES_Kd, [], "f");
 
-             for (let i = 0; i <= rounds; i++) {
 
-                 __classPrivateFieldGet$2(this, _AES_Ke, "f").push([0, 0, 0, 0]);
 
-                 __classPrivateFieldGet$2(this, _AES_Kd, "f").push([0, 0, 0, 0]);
 
-             }
 
-             const roundKeyCount = (rounds + 1) * 4;
 
-             const KC = this.key.length / 4;
 
-             // convert the key into ints
 
-             const tk = convertToInt32(this.key);
 
-             // copy values into round key arrays
 
-             let index;
 
-             for (let i = 0; i < KC; i++) {
 
-                 index = i >> 2;
 
-                 __classPrivateFieldGet$2(this, _AES_Ke, "f")[index][i % 4] = tk[i];
 
-                 __classPrivateFieldGet$2(this, _AES_Kd, "f")[rounds - index][i % 4] = tk[i];
 
-             }
 
-             // key expansion (fips-197 section 5.2)
 
-             let rconpointer = 0;
 
-             let t = KC, tt;
 
-             while (t < roundKeyCount) {
 
-                 tt = tk[KC - 1];
 
-                 tk[0] ^= ((S[(tt >> 16) & 0xFF] << 24) ^
 
-                     (S[(tt >> 8) & 0xFF] << 16) ^
 
-                     (S[tt & 0xFF] << 8) ^
 
-                     S[(tt >> 24) & 0xFF] ^
 
-                     (rcon[rconpointer] << 24));
 
-                 rconpointer += 1;
 
-                 // key expansion (for non-256 bit)
 
-                 if (KC != 8) {
 
-                     for (let i = 1; i < KC; i++) {
 
-                         tk[i] ^= tk[i - 1];
 
-                     }
 
-                     // key expansion for 256-bit keys is "slightly different" (fips-197)
 
-                 }
 
-                 else {
 
-                     for (let i = 1; i < (KC / 2); i++) {
 
-                         tk[i] ^= tk[i - 1];
 
-                     }
 
-                     tt = tk[(KC / 2) - 1];
 
-                     tk[KC / 2] ^= (S[tt & 0xFF] ^
 
-                         (S[(tt >> 8) & 0xFF] << 8) ^
 
-                         (S[(tt >> 16) & 0xFF] << 16) ^
 
-                         (S[(tt >> 24) & 0xFF] << 24));
 
-                     for (let i = (KC / 2) + 1; i < KC; i++) {
 
-                         tk[i] ^= tk[i - 1];
 
-                     }
 
-                 }
 
-                 // copy values into round key arrays
 
-                 let i = 0, r, c;
 
-                 while (i < KC && t < roundKeyCount) {
 
-                     r = t >> 2;
 
-                     c = t % 4;
 
-                     __classPrivateFieldGet$2(this, _AES_Ke, "f")[r][c] = tk[i];
 
-                     __classPrivateFieldGet$2(this, _AES_Kd, "f")[rounds - r][c] = tk[i++];
 
-                     t++;
 
-                 }
 
-             }
 
-             // inverse-cipher-ify the decryption round key (fips-197 section 5.3)
 
-             for (let r = 1; r < rounds; r++) {
 
-                 for (let c = 0; c < 4; c++) {
 
-                     tt = __classPrivateFieldGet$2(this, _AES_Kd, "f")[r][c];
 
-                     __classPrivateFieldGet$2(this, _AES_Kd, "f")[r][c] = (U1[(tt >> 24) & 0xFF] ^
 
-                         U2[(tt >> 16) & 0xFF] ^
 
-                         U3[(tt >> 8) & 0xFF] ^
 
-                         U4[tt & 0xFF]);
 
-                 }
 
-             }
 
-         }
 
-         encrypt(plaintext) {
 
-             if (plaintext.length != 16) {
 
-                 throw new TypeError('invalid plaintext size (must be 16 bytes)');
 
-             }
 
-             const rounds = __classPrivateFieldGet$2(this, _AES_Ke, "f").length - 1;
 
-             const a = [0, 0, 0, 0];
 
-             // convert plaintext to (ints ^ key)
 
-             let t = convertToInt32(plaintext);
 
-             for (let i = 0; i < 4; i++) {
 
-                 t[i] ^= __classPrivateFieldGet$2(this, _AES_Ke, "f")[0][i];
 
-             }
 
-             // apply round transforms
 
-             for (let r = 1; r < rounds; r++) {
 
-                 for (let i = 0; i < 4; i++) {
 
-                     a[i] = (T1[(t[i] >> 24) & 0xff] ^
 
-                         T2[(t[(i + 1) % 4] >> 16) & 0xff] ^
 
-                         T3[(t[(i + 2) % 4] >> 8) & 0xff] ^
 
-                         T4[t[(i + 3) % 4] & 0xff] ^
 
-                         __classPrivateFieldGet$2(this, _AES_Ke, "f")[r][i]);
 
-                 }
 
-                 t = a.slice();
 
-             }
 
-             // the last round is special
 
-             const result = new Uint8Array(16);
 
-             let tt = 0;
 
-             for (let i = 0; i < 4; i++) {
 
-                 tt = __classPrivateFieldGet$2(this, _AES_Ke, "f")[rounds][i];
 
-                 result[4 * i] = (S[(t[i] >> 24) & 0xff] ^ (tt >> 24)) & 0xff;
 
-                 result[4 * i + 1] = (S[(t[(i + 1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff;
 
-                 result[4 * i + 2] = (S[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff;
 
-                 result[4 * i + 3] = (S[t[(i + 3) % 4] & 0xff] ^ tt) & 0xff;
 
-             }
 
-             return result;
 
-         }
 
-         decrypt(ciphertext) {
 
-             if (ciphertext.length != 16) {
 
-                 throw new TypeError('invalid ciphertext size (must be 16 bytes)');
 
-             }
 
-             const rounds = __classPrivateFieldGet$2(this, _AES_Kd, "f").length - 1;
 
-             const a = [0, 0, 0, 0];
 
-             // convert plaintext to (ints ^ key)
 
-             let t = convertToInt32(ciphertext);
 
-             for (let i = 0; i < 4; i++) {
 
-                 t[i] ^= __classPrivateFieldGet$2(this, _AES_Kd, "f")[0][i];
 
-             }
 
-             // apply round transforms
 
-             for (let r = 1; r < rounds; r++) {
 
-                 for (let i = 0; i < 4; i++) {
 
-                     a[i] = (T5[(t[i] >> 24) & 0xff] ^
 
-                         T6[(t[(i + 3) % 4] >> 16) & 0xff] ^
 
-                         T7[(t[(i + 2) % 4] >> 8) & 0xff] ^
 
-                         T8[t[(i + 1) % 4] & 0xff] ^
 
-                         __classPrivateFieldGet$2(this, _AES_Kd, "f")[r][i]);
 
-                 }
 
-                 t = a.slice();
 
-             }
 
-             // the last round is special
 
-             const result = new Uint8Array(16);
 
-             let tt = 0;
 
-             for (let i = 0; i < 4; i++) {
 
-                 tt = __classPrivateFieldGet$2(this, _AES_Kd, "f")[rounds][i];
 
-                 result[4 * i] = (Si[(t[i] >> 24) & 0xff] ^ (tt >> 24)) & 0xff;
 
-                 result[4 * i + 1] = (Si[(t[(i + 3) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff;
 
-                 result[4 * i + 2] = (Si[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff;
 
-                 result[4 * i + 3] = (Si[t[(i + 1) % 4] & 0xff] ^ tt) & 0xff;
 
-             }
 
-             return result;
 
-         }
 
-     }
 
-     _AES_key = new WeakMap(), _AES_Kd = new WeakMap(), _AES_Ke = new WeakMap();
 
-     class ModeOfOperation {
 
-         constructor(name, key, cls) {
 
-             if (cls && !(this instanceof cls)) {
 
-                 throw new Error(`${name} must be instantiated with "new"`);
 
-             }
 
-             Object.defineProperties(this, {
 
-                 aes: { enumerable: true, value: new AES(key) },
 
-                 name: { enumerable: true, value: name }
 
-             });
 
-         }
 
-     }
 
-     // Cipher Block Chaining
 
-     var __classPrivateFieldSet$1 = (__$G && __$G.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
 
-         if (kind === "m") throw new TypeError("Private method is not writable");
 
-         if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
 
-         if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
 
-         return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
 
-     };
 
-     var __classPrivateFieldGet$1 = (__$G && __$G.__classPrivateFieldGet) || function (receiver, state, kind, f) {
 
-         if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
 
-         if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
 
-         return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
 
-     };
 
-     var _CBC_iv, _CBC_lastBlock;
 
-     class CBC extends ModeOfOperation {
 
-         constructor(key, iv) {
 
-             super("ECC", key, CBC);
 
-             _CBC_iv.set(this, void 0);
 
-             _CBC_lastBlock.set(this, void 0);
 
-             if (iv) {
 
-                 if (iv.length % 16) {
 
-                     throw new TypeError("invalid iv size (must be 16 bytes)");
 
-                 }
 
-                 __classPrivateFieldSet$1(this, _CBC_iv, new Uint8Array(iv), "f");
 
-             }
 
-             else {
 
-                 __classPrivateFieldSet$1(this, _CBC_iv, new Uint8Array(16), "f");
 
-             }
 
-             __classPrivateFieldSet$1(this, _CBC_lastBlock, this.iv, "f");
 
-         }
 
-         get iv() { return new Uint8Array(__classPrivateFieldGet$1(this, _CBC_iv, "f")); }
 
-         encrypt(plaintext) {
 
-             if (plaintext.length % 16) {
 
-                 throw new TypeError("invalid plaintext size (must be multiple of 16 bytes)");
 
-             }
 
-             const ciphertext = new Uint8Array(plaintext.length);
 
-             for (let i = 0; i < plaintext.length; i += 16) {
 
-                 for (let j = 0; j < 16; j++) {
 
-                     __classPrivateFieldGet$1(this, _CBC_lastBlock, "f")[j] ^= plaintext[i + j];
 
-                 }
 
-                 __classPrivateFieldSet$1(this, _CBC_lastBlock, this.aes.encrypt(__classPrivateFieldGet$1(this, _CBC_lastBlock, "f")), "f");
 
-                 ciphertext.set(__classPrivateFieldGet$1(this, _CBC_lastBlock, "f"), i);
 
-             }
 
-             return ciphertext;
 
-         }
 
-         decrypt(ciphertext) {
 
-             if (ciphertext.length % 16) {
 
-                 throw new TypeError("invalid ciphertext size (must be multiple of 16 bytes)");
 
-             }
 
-             const plaintext = new Uint8Array(ciphertext.length);
 
-             for (let i = 0; i < ciphertext.length; i += 16) {
 
-                 const block = this.aes.decrypt(ciphertext.subarray(i, i + 16));
 
-                 for (let j = 0; j < 16; j++) {
 
-                     plaintext[i + j] = block[j] ^ __classPrivateFieldGet$1(this, _CBC_lastBlock, "f")[j];
 
-                     __classPrivateFieldGet$1(this, _CBC_lastBlock, "f")[j] = ciphertext[i + j];
 
-                 }
 
-             }
 
-             return plaintext;
 
-         }
 
-     }
 
-     _CBC_iv = new WeakMap(), _CBC_lastBlock = new WeakMap();
 
-     // Counter Mode
 
-     var __classPrivateFieldSet = (__$G && __$G.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
 
-         if (kind === "m") throw new TypeError("Private method is not writable");
 
-         if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
 
-         if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
 
-         return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
 
-     };
 
-     var __classPrivateFieldGet = (__$G && __$G.__classPrivateFieldGet) || function (receiver, state, kind, f) {
 
-         if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
 
-         if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
 
-         return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
 
-     };
 
-     var _CTR_remaining, _CTR_remainingIndex, _CTR_counter;
 
-     class CTR extends ModeOfOperation {
 
-         constructor(key, initialValue) {
 
-             super("CTR", key, CTR);
 
-             // Remaining bytes for the one-time pad
 
-             _CTR_remaining.set(this, void 0);
 
-             _CTR_remainingIndex.set(this, void 0);
 
-             // The current counter
 
-             _CTR_counter.set(this, void 0);
 
-             __classPrivateFieldSet(this, _CTR_counter, new Uint8Array(16), "f");
 
-             __classPrivateFieldGet(this, _CTR_counter, "f").fill(0);
 
-             __classPrivateFieldSet(this, _CTR_remaining, __classPrivateFieldGet(this, _CTR_counter, "f"), "f"); // This will be discarded immediately
 
-             __classPrivateFieldSet(this, _CTR_remainingIndex, 16, "f");
 
-             if (initialValue == null) {
 
-                 initialValue = 1;
 
-             }
 
-             if (typeof (initialValue) === "number") {
 
-                 this.setCounterValue(initialValue);
 
-             }
 
-             else {
 
-                 this.setCounterBytes(initialValue);
 
-             }
 
-         }
 
-         get counter() { return new Uint8Array(__classPrivateFieldGet(this, _CTR_counter, "f")); }
 
-         setCounterValue(value) {
 
-             if (!Number.isInteger(value) || value < 0 || value > Number.MAX_SAFE_INTEGER) {
 
-                 throw new TypeError("invalid counter initial integer value");
 
-             }
 
-             for (let index = 15; index >= 0; --index) {
 
-                 __classPrivateFieldGet(this, _CTR_counter, "f")[index] = value % 256;
 
-                 value = Math.floor(value / 256);
 
-             }
 
-         }
 
-         setCounterBytes(value) {
 
-             if (value.length !== 16) {
 
-                 throw new TypeError("invalid counter initial Uint8Array value length");
 
-             }
 
-             __classPrivateFieldGet(this, _CTR_counter, "f").set(value);
 
-         }
 
-         increment() {
 
-             for (let i = 15; i >= 0; i--) {
 
-                 if (__classPrivateFieldGet(this, _CTR_counter, "f")[i] === 255) {
 
-                     __classPrivateFieldGet(this, _CTR_counter, "f")[i] = 0;
 
-                 }
 
-                 else {
 
-                     __classPrivateFieldGet(this, _CTR_counter, "f")[i]++;
 
-                     break;
 
-                 }
 
-             }
 
-         }
 
-         encrypt(plaintext) {
 
-             var _a, _b;
 
-             const crypttext = new Uint8Array(plaintext);
 
-             for (let i = 0; i < crypttext.length; i++) {
 
-                 if (__classPrivateFieldGet(this, _CTR_remainingIndex, "f") === 16) {
 
-                     __classPrivateFieldSet(this, _CTR_remaining, this.aes.encrypt(__classPrivateFieldGet(this, _CTR_counter, "f")), "f");
 
-                     __classPrivateFieldSet(this, _CTR_remainingIndex, 0, "f");
 
-                     this.increment();
 
-                 }
 
-                 crypttext[i] ^= __classPrivateFieldGet(this, _CTR_remaining, "f")[__classPrivateFieldSet(this, _CTR_remainingIndex, (_b = __classPrivateFieldGet(this, _CTR_remainingIndex, "f"), _a = _b++, _b), "f"), _a];
 
-             }
 
-             return crypttext;
 
-         }
 
-         decrypt(ciphertext) {
 
-             return this.encrypt(ciphertext);
 
-         }
 
-     }
 
-     _CTR_remaining = new WeakMap(), _CTR_remainingIndex = new WeakMap(), _CTR_counter = new WeakMap();
 
-     function pkcs7Strip(data) {
 
-         if (data.length < 16) {
 
-             throw new TypeError('PKCS#7 invalid length');
 
-         }
 
-         const padder = data[data.length - 1];
 
-         if (padder > 16) {
 
-             throw new TypeError('PKCS#7 padding byte out of range');
 
-         }
 
-         const length = data.length - padder;
 
-         for (let i = 0; i < padder; i++) {
 
-             if (data[length + i] !== padder) {
 
-                 throw new TypeError('PKCS#7 invalid padding byte');
 
-             }
 
-         }
 
-         return new Uint8Array(data.subarray(0, length));
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     function looseArrayify(hexString) {
 
-         if (typeof (hexString) === "string" && !hexString.startsWith("0x")) {
 
-             hexString = "0x" + hexString;
 
-         }
 
-         return getBytesCopy(hexString);
 
-     }
 
-     function zpad$1(value, length) {
 
-         value = String(value);
 
-         while (value.length < length) {
 
-             value = '0' + value;
 
-         }
 
-         return value;
 
-     }
 
-     function getPassword(password) {
 
-         if (typeof (password) === 'string') {
 
-             return toUtf8Bytes(password, "NFKC");
 
-         }
 
-         return getBytesCopy(password);
 
-     }
 
-     function spelunk(object, _path) {
 
-         const match = _path.match(/^([a-z0-9$_.-]*)(:([a-z]+))?(!)?$/i);
 
-         assertArgument(match != null, "invalid path", "path", _path);
 
-         const path = match[1];
 
-         const type = match[3];
 
-         const reqd = (match[4] === "!");
 
-         let cur = object;
 
-         for (const comp of path.toLowerCase().split('.')) {
 
-             // Search for a child object with a case-insensitive matching key
 
-             if (Array.isArray(cur)) {
 
-                 if (!comp.match(/^[0-9]+$/)) {
 
-                     break;
 
-                 }
 
-                 cur = cur[parseInt(comp)];
 
-             }
 
-             else if (typeof (cur) === "object") {
 
-                 let found = null;
 
-                 for (const key in cur) {
 
-                     if (key.toLowerCase() === comp) {
 
-                         found = cur[key];
 
-                         break;
 
-                     }
 
-                 }
 
-                 cur = found;
 
-             }
 
-             else {
 
-                 cur = null;
 
-             }
 
-             if (cur == null) {
 
-                 break;
 
-             }
 
-         }
 
-         assertArgument(!reqd || cur != null, "missing required value", "path", path);
 
-         if (type && cur != null) {
 
-             if (type === "int") {
 
-                 if (typeof (cur) === "string" && cur.match(/^-?[0-9]+$/)) {
 
-                     return parseInt(cur);
 
-                 }
 
-                 else if (Number.isSafeInteger(cur)) {
 
-                     return cur;
 
-                 }
 
-             }
 
-             if (type === "number") {
 
-                 if (typeof (cur) === "string" && cur.match(/^-?[0-9.]*$/)) {
 
-                     return parseFloat(cur);
 
-                 }
 
-             }
 
-             if (type === "data") {
 
-                 if (typeof (cur) === "string") {
 
-                     return looseArrayify(cur);
 
-                 }
 
-             }
 
-             if (type === "array" && Array.isArray(cur)) {
 
-                 return cur;
 
-             }
 
-             if (type === typeof (cur)) {
 
-                 return cur;
 
-             }
 
-             assertArgument(false, `wrong type found for ${type} `, "path", path);
 
-         }
 
-         return cur;
 
-     }
 
-     /*
 
-     export function follow(object: any, path: string): null | string {
 
-         let currentChild = object;
 
-         for (const comp of path.toLowerCase().split('/')) {
 
-             // Search for a child object with a case-insensitive matching key
 
-             let matchingChild = null;
 
-             for (const key in currentChild) {
 
-                  if (key.toLowerCase() === comp) {
 
-                      matchingChild = currentChild[key];
 
-                      break;
 
-                  }
 
-             }
 
-             if (matchingChild === null) { return null; }
 
-             currentChild = matchingChild;
 
-         }
 
-         return currentChild;
 
-     }
 
-     // "path/to/something:type!"
 
-     export function followRequired(data: any, path: string): string {
 
-         const value = follow(data, path);
 
-         if (value != null) { return value; }
 
-         return logger.throwArgumentError("invalid value", `data:${ path }`,
 
-         JSON.stringify(data));
 
-     }
 
-     */
 
-     // See: https://www.ietf.org/rfc/rfc4122.txt (Section 4.4)
 
-     /*
 
-     export function uuidV4(randomBytes: BytesLike): string {
 
-         const bytes = getBytes(randomBytes, "randomBytes");
 
-         // Section: 4.1.3:
 
-         // - time_hi_and_version[12:16] = 0b0100
 
-         bytes[6] = (bytes[6] & 0x0f) | 0x40;
 
-         // Section 4.4
 
-         // - clock_seq_hi_and_reserved[6] = 0b0
 
-         // - clock_seq_hi_and_reserved[7] = 0b1
 
-         bytes[8] = (bytes[8] & 0x3f) | 0x80;
 
-         const value = hexlify(bytes);
 
-         return [
 
-            value.substring(2, 10),
 
-            value.substring(10, 14),
 
-            value.substring(14, 18),
 
-            value.substring(18, 22),
 
-            value.substring(22, 34),
 
-         ].join("-");
 
-     }
 
-     */
 
-     /**
 
-      *  The JSON Wallet formats allow a simple way to store the private
 
-      *  keys needed in Ethereum along with related information and allows
 
-      *  for extensible forms of encryption.
 
-      *
 
-      *  These utilities facilitate decrypting and encrypting the most common
 
-      *  JSON Wallet formats.
 
-      *
 
-      *  @_subsection: api/wallet:JSON Wallets  [json-wallets]
 
-      */
 
-     const defaultPath$1 = "m/44'/60'/0'/0/0";
 
-     /**
 
-      *  Returns true if %%json%% is a valid JSON Keystore Wallet.
 
-      */
 
-     function isKeystoreJson(json) {
 
-         try {
 
-             const data = JSON.parse(json);
 
-             const version = ((data.version != null) ? parseInt(data.version) : 0);
 
-             if (version === 3) {
 
-                 return true;
 
-             }
 
-         }
 
-         catch (error) { }
 
-         return false;
 
-     }
 
-     function decrypt(data, key, ciphertext) {
 
-         const cipher = spelunk(data, "crypto.cipher:string");
 
-         if (cipher === "aes-128-ctr") {
 
-             const iv = spelunk(data, "crypto.cipherparams.iv:data!");
 
-             const aesCtr = new CTR(key, iv);
 
-             return hexlify(aesCtr.decrypt(ciphertext));
 
-         }
 
-         assert(false, "unsupported cipher", "UNSUPPORTED_OPERATION", {
 
-             operation: "decrypt"
 
-         });
 
-     }
 
-     function getAccount(data, _key) {
 
-         const key = getBytes(_key);
 
-         const ciphertext = spelunk(data, "crypto.ciphertext:data!");
 
-         const computedMAC = hexlify(keccak256(concat([key.slice(16, 32), ciphertext]))).substring(2);
 
-         assertArgument(computedMAC === spelunk(data, "crypto.mac:string!").toLowerCase(), "incorrect password", "password", "[ REDACTED ]");
 
-         const privateKey = decrypt(data, key.slice(0, 16), ciphertext);
 
-         const address = computeAddress(privateKey);
 
-         if (data.address) {
 
-             let check = data.address.toLowerCase();
 
-             if (!check.startsWith("0x")) {
 
-                 check = "0x" + check;
 
-             }
 
-             assertArgument(getAddress(check) === address, "keystore address/privateKey mismatch", "address", data.address);
 
-         }
 
-         const account = { address, privateKey };
 
-         // Version 0.1 x-ethers metadata must contain an encrypted mnemonic phrase
 
-         const version = spelunk(data, "x-ethers.version:string");
 
-         if (version === "0.1") {
 
-             const mnemonicKey = key.slice(32, 64);
 
-             const mnemonicCiphertext = spelunk(data, "x-ethers.mnemonicCiphertext:data!");
 
-             const mnemonicIv = spelunk(data, "x-ethers.mnemonicCounter:data!");
 
-             const mnemonicAesCtr = new CTR(mnemonicKey, mnemonicIv);
 
-             account.mnemonic = {
 
-                 path: (spelunk(data, "x-ethers.path:string") || defaultPath$1),
 
-                 locale: (spelunk(data, "x-ethers.locale:string") || "en"),
 
-                 entropy: hexlify(getBytes(mnemonicAesCtr.decrypt(mnemonicCiphertext)))
 
-             };
 
-         }
 
-         return account;
 
-     }
 
-     function getDecryptKdfParams(data) {
 
-         const kdf = spelunk(data, "crypto.kdf:string");
 
-         if (kdf && typeof (kdf) === "string") {
 
-             if (kdf.toLowerCase() === "scrypt") {
 
-                 const salt = spelunk(data, "crypto.kdfparams.salt:data!");
 
-                 const N = spelunk(data, "crypto.kdfparams.n:int!");
 
-                 const r = spelunk(data, "crypto.kdfparams.r:int!");
 
-                 const p = spelunk(data, "crypto.kdfparams.p:int!");
 
-                 // Make sure N is a power of 2
 
-                 assertArgument(N > 0 && (N & (N - 1)) === 0, "invalid kdf.N", "kdf.N", N);
 
-                 assertArgument(r > 0 && p > 0, "invalid kdf", "kdf", kdf);
 
-                 const dkLen = spelunk(data, "crypto.kdfparams.dklen:int!");
 
-                 assertArgument(dkLen === 32, "invalid kdf.dklen", "kdf.dflen", dkLen);
 
-                 return { name: "scrypt", salt, N, r, p, dkLen: 64 };
 
-             }
 
-             else if (kdf.toLowerCase() === "pbkdf2") {
 
-                 const salt = spelunk(data, "crypto.kdfparams.salt:data!");
 
-                 const prf = spelunk(data, "crypto.kdfparams.prf:string!");
 
-                 const algorithm = prf.split("-").pop();
 
-                 assertArgument(algorithm === "sha256" || algorithm === "sha512", "invalid kdf.pdf", "kdf.pdf", prf);
 
-                 const count = spelunk(data, "crypto.kdfparams.c:int!");
 
-                 const dkLen = spelunk(data, "crypto.kdfparams.dklen:int!");
 
-                 assertArgument(dkLen === 32, "invalid kdf.dklen", "kdf.dklen", dkLen);
 
-                 return { name: "pbkdf2", salt, count, dkLen, algorithm };
 
-             }
 
-         }
 
-         assertArgument(false, "unsupported key-derivation function", "kdf", kdf);
 
-     }
 
-     /**
 
-      *  Returns the account details for the JSON Keystore Wallet %%json%%
 
-      *  using %%password%%.
 
-      *
 
-      *  It is preferred to use the [async version](decryptKeystoreJson)
 
-      *  instead, which allows a [[ProgressCallback]] to keep the user informed
 
-      *  as to the decryption status.
 
-      *
 
-      *  This method will block the event loop (freezing all UI) until decryption
 
-      *  is complete, which can take quite some time, depending on the wallet
 
-      *  paramters and platform.
 
-      */
 
-     function decryptKeystoreJsonSync(json, _password) {
 
-         const data = JSON.parse(json);
 
-         const password = getPassword(_password);
 
-         const params = getDecryptKdfParams(data);
 
-         if (params.name === "pbkdf2") {
 
-             const { salt, count, dkLen, algorithm } = params;
 
-             const key = pbkdf2(password, salt, count, dkLen, algorithm);
 
-             return getAccount(data, key);
 
-         }
 
-         assert(params.name === "scrypt", "cannot be reached", "UNKNOWN_ERROR", { params });
 
-         const { salt, N, r, p, dkLen } = params;
 
-         const key = scryptSync(password, salt, N, r, p, dkLen);
 
-         return getAccount(data, key);
 
-     }
 
-     function stall$1(duration) {
 
-         return new Promise((resolve) => { setTimeout(() => { resolve(); }, duration); });
 
-     }
 
-     /**
 
-      *  Resolves to the decrypted JSON Keystore Wallet %%json%% using the
 
-      *  %%password%%.
 
-      *
 
-      *  If provided, %%progress%% will be called periodically during the
 
-      *  decrpytion to provide feedback, and if the function returns
 
-      *  ``false`` will halt decryption.
 
-      *
 
-      *  The %%progressCallback%% will **always** receive ``0`` before
 
-      *  decryption begins and ``1`` when complete.
 
-      */
 
-     async function decryptKeystoreJson(json, _password, progress) {
 
-         const data = JSON.parse(json);
 
-         const password = getPassword(_password);
 
-         const params = getDecryptKdfParams(data);
 
-         if (params.name === "pbkdf2") {
 
-             if (progress) {
 
-                 progress(0);
 
-                 await stall$1(0);
 
-             }
 
-             const { salt, count, dkLen, algorithm } = params;
 
-             const key = pbkdf2(password, salt, count, dkLen, algorithm);
 
-             if (progress) {
 
-                 progress(1);
 
-                 await stall$1(0);
 
-             }
 
-             return getAccount(data, key);
 
-         }
 
-         assert(params.name === "scrypt", "cannot be reached", "UNKNOWN_ERROR", { params });
 
-         const { salt, N, r, p, dkLen } = params;
 
-         const key = await scrypt(password, salt, N, r, p, dkLen, progress);
 
-         return getAccount(data, key);
 
-     }
 
-     function getEncryptKdfParams(options) {
 
-         // Check/generate the salt
 
-         const salt = (options.salt != null) ? getBytes(options.salt, "options.salt") : randomBytes(32);
 
-         // Override the scrypt password-based key derivation function parameters
 
-         let N = (1 << 17), r = 8, p = 1;
 
-         if (options.scrypt) {
 
-             if (options.scrypt.N) {
 
-                 N = options.scrypt.N;
 
-             }
 
-             if (options.scrypt.r) {
 
-                 r = options.scrypt.r;
 
-             }
 
-             if (options.scrypt.p) {
 
-                 p = options.scrypt.p;
 
-             }
 
-         }
 
-         assertArgument(typeof (N) === "number" && N > 0 && Number.isSafeInteger(N) && (BigInt(N) & BigInt(N - 1)) === BigInt(0), "invalid scrypt N parameter", "options.N", N);
 
-         assertArgument(typeof (r) === "number" && r > 0 && Number.isSafeInteger(r), "invalid scrypt r parameter", "options.r", r);
 
-         assertArgument(typeof (p) === "number" && p > 0 && Number.isSafeInteger(p), "invalid scrypt p parameter", "options.p", p);
 
-         return { name: "scrypt", dkLen: 32, salt, N, r, p };
 
-     }
 
-     function _encryptKeystore(key, kdf, account, options) {
 
-         const privateKey = getBytes(account.privateKey, "privateKey");
 
-         // Override initialization vector
 
-         const iv = (options.iv != null) ? getBytes(options.iv, "options.iv") : randomBytes(16);
 
-         assertArgument(iv.length === 16, "invalid options.iv length", "options.iv", options.iv);
 
-         // Override the uuid
 
-         const uuidRandom = (options.uuid != null) ? getBytes(options.uuid, "options.uuid") : randomBytes(16);
 
-         assertArgument(uuidRandom.length === 16, "invalid options.uuid length", "options.uuid", options.iv);
 
-         // This will be used to encrypt the wallet (as per Web3 secret storage)
 
-         // - 32 bytes   As normal for the Web3 secret storage (derivedKey, macPrefix)
 
-         // - 32 bytes   AES key to encrypt mnemonic with (required here to be Ethers Wallet)
 
-         const derivedKey = key.slice(0, 16);
 
-         const macPrefix = key.slice(16, 32);
 
-         // Encrypt the private key
 
-         const aesCtr = new CTR(derivedKey, iv);
 
-         const ciphertext = getBytes(aesCtr.encrypt(privateKey));
 
-         // Compute the message authentication code, used to check the password
 
-         const mac = keccak256(concat([macPrefix, ciphertext]));
 
-         // See: https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition
 
-         const data = {
 
-             address: account.address.substring(2).toLowerCase(),
 
-             id: uuidV4(uuidRandom),
 
-             version: 3,
 
-             Crypto: {
 
-                 cipher: "aes-128-ctr",
 
-                 cipherparams: {
 
-                     iv: hexlify(iv).substring(2),
 
-                 },
 
-                 ciphertext: hexlify(ciphertext).substring(2),
 
-                 kdf: "scrypt",
 
-                 kdfparams: {
 
-                     salt: hexlify(kdf.salt).substring(2),
 
-                     n: kdf.N,
 
-                     dklen: 32,
 
-                     p: kdf.p,
 
-                     r: kdf.r
 
-                 },
 
-                 mac: mac.substring(2)
 
-             }
 
-         };
 
-         // If we have a mnemonic, encrypt it into the JSON wallet
 
-         if (account.mnemonic) {
 
-             const client = (options.client != null) ? options.client : `ethers/${version}`;
 
-             const path = account.mnemonic.path || defaultPath$1;
 
-             const locale = account.mnemonic.locale || "en";
 
-             const mnemonicKey = key.slice(32, 64);
 
-             const entropy = getBytes(account.mnemonic.entropy, "account.mnemonic.entropy");
 
-             const mnemonicIv = randomBytes(16);
 
-             const mnemonicAesCtr = new CTR(mnemonicKey, mnemonicIv);
 
-             const mnemonicCiphertext = getBytes(mnemonicAesCtr.encrypt(entropy));
 
-             const now = new Date();
 
-             const timestamp = (now.getUTCFullYear() + "-" +
 
-                 zpad$1(now.getUTCMonth() + 1, 2) + "-" +
 
-                 zpad$1(now.getUTCDate(), 2) + "T" +
 
-                 zpad$1(now.getUTCHours(), 2) + "-" +
 
-                 zpad$1(now.getUTCMinutes(), 2) + "-" +
 
-                 zpad$1(now.getUTCSeconds(), 2) + ".0Z");
 
-             const gethFilename = ("UTC--" + timestamp + "--" + data.address);
 
-             data["x-ethers"] = {
 
-                 client, gethFilename, path, locale,
 
-                 mnemonicCounter: hexlify(mnemonicIv).substring(2),
 
-                 mnemonicCiphertext: hexlify(mnemonicCiphertext).substring(2),
 
-                 version: "0.1"
 
-             };
 
-         }
 
-         return JSON.stringify(data);
 
-     }
 
-     /**
 
-      *  Return the JSON Keystore Wallet for %%account%% encrypted with
 
-      *  %%password%%.
 
-      *
 
-      *  The %%options%% can be used to tune the password-based key
 
-      *  derivation function parameters, explicitly set the random values
 
-      *  used. Any provided [[ProgressCallback]] is ignord.
 
-      */
 
-     function encryptKeystoreJsonSync(account, password, options) {
 
-         if (options == null) {
 
-             options = {};
 
-         }
 
-         const passwordBytes = getPassword(password);
 
-         const kdf = getEncryptKdfParams(options);
 
-         const key = scryptSync(passwordBytes, kdf.salt, kdf.N, kdf.r, kdf.p, 64);
 
-         return _encryptKeystore(getBytes(key), kdf, account, options);
 
-     }
 
-     /**
 
-      *  Resolved to the JSON Keystore Wallet for %%account%% encrypted
 
-      *  with %%password%%.
 
-      *
 
-      *  The %%options%% can be used to tune the password-based key
 
-      *  derivation function parameters, explicitly set the random values
 
-      *  used and provide a [[ProgressCallback]] to receive periodic updates
 
-      *  on the completion status..
 
-      */
 
-     async function encryptKeystoreJson(account, password, options) {
 
-         if (options == null) {
 
-             options = {};
 
-         }
 
-         const passwordBytes = getPassword(password);
 
-         const kdf = getEncryptKdfParams(options);
 
-         const key = await scrypt(passwordBytes, kdf.salt, kdf.N, kdf.r, kdf.p, 64, options.progressCallback);
 
-         return _encryptKeystore(getBytes(key), kdf, account, options);
 
-     }
 
-     /**
 
-      *  Explain HD Wallets..
 
-      *
 
-      *  @_subsection: api/wallet:HD Wallets  [hd-wallets]
 
-      */
 
-     /**
 
-      *  The default derivation path for Ethereum HD Nodes. (i.e. ``"m/44'/60'/0'/0/0"``)
 
-      */
 
-     const defaultPath = "m/44'/60'/0'/0/0";
 
-     // "Bitcoin seed"
 
-     const MasterSecret = new Uint8Array([66, 105, 116, 99, 111, 105, 110, 32, 115, 101, 101, 100]);
 
-     const HardenedBit = 0x80000000;
 
-     const N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
 
-     const Nibbles = "0123456789abcdef";
 
-     function zpad(value, length) {
 
-         let result = "";
 
-         while (value) {
 
-             result = Nibbles[value % 16] + result;
 
-             value = Math.trunc(value / 16);
 
-         }
 
-         while (result.length < length * 2) {
 
-             result = "0" + result;
 
-         }
 
-         return "0x" + result;
 
-     }
 
-     function encodeBase58Check(_value) {
 
-         const value = getBytes(_value);
 
-         const check = dataSlice(sha256(sha256(value)), 0, 4);
 
-         const bytes = concat([value, check]);
 
-         return encodeBase58(bytes);
 
-     }
 
-     const _guard = {};
 
-     function ser_I(index, chainCode, publicKey, privateKey) {
 
-         const data = new Uint8Array(37);
 
-         if (index & HardenedBit) {
 
-             assert(privateKey != null, "cannot derive child of neutered node", "UNSUPPORTED_OPERATION", {
 
-                 operation: "deriveChild"
 
-             });
 
-             // Data = 0x00 || ser_256(k_par)
 
-             data.set(getBytes(privateKey), 1);
 
-         }
 
-         else {
 
-             // Data = ser_p(point(k_par))
 
-             data.set(getBytes(publicKey));
 
-         }
 
-         // Data += ser_32(i)
 
-         for (let i = 24; i >= 0; i -= 8) {
 
-             data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff);
 
-         }
 
-         const I = getBytes(computeHmac("sha512", chainCode, data));
 
-         return { IL: I.slice(0, 32), IR: I.slice(32) };
 
-     }
 
-     function derivePath(node, path) {
 
-         const components = path.split("/");
 
-         assertArgument(components.length > 0, "invalid path", "path", path);
 
-         if (components[0] === "m") {
 
-             assertArgument(node.depth === 0, `cannot derive root path (i.e. path starting with "m/") for a node at non-zero depth ${node.depth}`, "path", path);
 
-             components.shift();
 
-         }
 
-         let result = node;
 
-         for (let i = 0; i < components.length; i++) {
 
-             const component = components[i];
 
-             if (component.match(/^[0-9]+'$/)) {
 
-                 const index = parseInt(component.substring(0, component.length - 1));
 
-                 assertArgument(index < HardenedBit, "invalid path index", `path[${i}]`, component);
 
-                 result = result.deriveChild(HardenedBit + index);
 
-             }
 
-             else if (component.match(/^[0-9]+$/)) {
 
-                 const index = parseInt(component);
 
-                 assertArgument(index < HardenedBit, "invalid path index", `path[${i}]`, component);
 
-                 result = result.deriveChild(index);
 
-             }
 
-             else {
 
-                 assertArgument(false, "invalid path component", `path[${i}]`, component);
 
-             }
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  An **HDNodeWallet** is a [[Signer]] backed by the private key derived
 
-      *  from an HD Node using the [[link-bip-32]] stantard.
 
-      *
 
-      *  An HD Node forms a hierarchal structure with each HD Node having a
 
-      *  private key and the ability to derive child HD Nodes, defined by
 
-      *  a path indicating the index of each child.
 
-      */
 
-     class HDNodeWallet extends BaseWallet {
 
-         /**
 
-          *  The compressed public key.
 
-          */
 
-         publicKey;
 
-         /**
 
-          *  The fingerprint.
 
-          *
 
-          *  A fingerprint allows quick qay to detect parent and child nodes,
 
-          *  but developers should be prepared to deal with collisions as it
 
-          *  is only 4 bytes.
 
-          */
 
-         fingerprint;
 
-         /**
 
-          *  The parent fingerprint.
 
-          */
 
-         parentFingerprint;
 
-         /**
 
-          *  The mnemonic used to create this HD Node, if available.
 
-          *
 
-          *  Sources such as extended keys do not encode the mnemonic, in
 
-          *  which case this will be ``null``.
 
-          */
 
-         mnemonic;
 
-         /**
 
-          *  The chaincode, which is effectively a public key used
 
-          *  to derive children.
 
-          */
 
-         chainCode;
 
-         /**
 
-          *  The derivation path of this wallet.
 
-          *
 
-          *  Since extended keys do not provide full path details, this
 
-          *  may be ``null``, if instantiated from a source that does not
 
-          *  encode it.
 
-          */
 
-         path;
 
-         /**
 
-          *  The child index of this wallet. Values over ``2 *\* 31`` indicate
 
-          *  the node is hardened.
 
-          */
 
-         index;
 
-         /**
 
-          *  The depth of this wallet, which is the number of components
 
-          *  in its path.
 
-          */
 
-         depth;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, signingKey, parentFingerprint, chainCode, path, index, depth, mnemonic, provider) {
 
-             super(signingKey, provider);
 
-             assertPrivate(guard, _guard, "HDNodeWallet");
 
-             defineProperties(this, { publicKey: signingKey.compressedPublicKey });
 
-             const fingerprint = dataSlice(ripemd160(sha256(this.publicKey)), 0, 4);
 
-             defineProperties(this, {
 
-                 parentFingerprint, fingerprint,
 
-                 chainCode, path, index, depth
 
-             });
 
-             defineProperties(this, { mnemonic });
 
-         }
 
-         connect(provider) {
 
-             return new HDNodeWallet(_guard, this.signingKey, this.parentFingerprint, this.chainCode, this.path, this.index, this.depth, this.mnemonic, provider);
 
-         }
 
-         #account() {
 
-             const account = { address: this.address, privateKey: this.privateKey };
 
-             const m = this.mnemonic;
 
-             if (this.path && m && m.wordlist.locale === "en" && m.password === "") {
 
-                 account.mnemonic = {
 
-                     path: this.path,
 
-                     locale: "en",
 
-                     entropy: m.entropy
 
-                 };
 
-             }
 
-             return account;
 
-         }
 
-         /**
 
-          *  Resolves to a [JSON Keystore Wallet](json-wallets) encrypted with
 
-          *  %%password%%.
 
-          *
 
-          *  If %%progressCallback%% is specified, it will receive periodic
 
-          *  updates as the encryption process progreses.
 
-          */
 
-         async encrypt(password, progressCallback) {
 
-             return await encryptKeystoreJson(this.#account(), password, { progressCallback });
 
-         }
 
-         /**
 
-          *  Returns a [JSON Keystore Wallet](json-wallets) encryped with
 
-          *  %%password%%.
 
-          *
 
-          *  It is preferred to use the [async version](encrypt) instead,
 
-          *  which allows a [[ProgressCallback]] to keep the user informed.
 
-          *
 
-          *  This method will block the event loop (freezing all UI) until
 
-          *  it is complete, which may be a non-trivial duration.
 
-          */
 
-         encryptSync(password) {
 
-             return encryptKeystoreJsonSync(this.#account(), password);
 
-         }
 
-         /**
 
-          *  The extended key.
 
-          *
 
-          *  This key will begin with the prefix ``xpriv`` and can be used to
 
-          *  reconstruct this HD Node to derive its children.
 
-          */
 
-         get extendedKey() {
 
-             // We only support the mainnet values for now, but if anyone needs
 
-             // testnet values, let me know. I believe current sentiment is that
 
-             // we should always use mainnet, and use BIP-44 to derive the network
 
-             //   - Mainnet: public=0x0488B21E, private=0x0488ADE4
 
-             //   - Testnet: public=0x043587CF, private=0x04358394
 
-             assert(this.depth < 256, "Depth too deep", "UNSUPPORTED_OPERATION", { operation: "extendedKey" });
 
-             return encodeBase58Check(concat([
 
-                 "0x0488ADE4", zpad(this.depth, 1), this.parentFingerprint,
 
-                 zpad(this.index, 4), this.chainCode,
 
-                 concat(["0x00", this.privateKey])
 
-             ]));
 
-         }
 
-         /**
 
-          *  Returns true if this wallet has a path, providing a Type Guard
 
-          *  that the path is non-null.
 
-          */
 
-         hasPath() { return (this.path != null); }
 
-         /**
 
-          *  Returns a neutered HD Node, which removes the private details
 
-          *  of an HD Node.
 
-          *
 
-          *  A neutered node has no private key, but can be used to derive
 
-          *  child addresses and other public data about the HD Node.
 
-          */
 
-         neuter() {
 
-             return new HDNodeVoidWallet(_guard, this.address, this.publicKey, this.parentFingerprint, this.chainCode, this.path, this.index, this.depth, this.provider);
 
-         }
 
-         /**
 
-          *  Return the child for %%index%%.
 
-          */
 
-         deriveChild(_index) {
 
-             const index = getNumber(_index, "index");
 
-             assertArgument(index <= 0xffffffff, "invalid index", "index", index);
 
-             // Base path
 
-             let path = this.path;
 
-             if (path) {
 
-                 path += "/" + (index & ~HardenedBit);
 
-                 if (index & HardenedBit) {
 
-                     path += "'";
 
-                 }
 
-             }
 
-             const { IR, IL } = ser_I(index, this.chainCode, this.publicKey, this.privateKey);
 
-             const ki = new SigningKey(toBeHex((toBigInt(IL) + BigInt(this.privateKey)) % N, 32));
 
-             return new HDNodeWallet(_guard, ki, this.fingerprint, hexlify(IR), path, index, this.depth + 1, this.mnemonic, this.provider);
 
-         }
 
-         /**
 
-          *  Return the HDNode for %%path%% from this node.
 
-          */
 
-         derivePath(path) {
 
-             return derivePath(this, path);
 
-         }
 
-         static #fromSeed(_seed, mnemonic) {
 
-             assertArgument(isBytesLike(_seed), "invalid seed", "seed", "[REDACTED]");
 
-             const seed = getBytes(_seed, "seed");
 
-             assertArgument(seed.length >= 16 && seed.length <= 64, "invalid seed", "seed", "[REDACTED]");
 
-             const I = getBytes(computeHmac("sha512", MasterSecret, seed));
 
-             const signingKey = new SigningKey(hexlify(I.slice(0, 32)));
 
-             return new HDNodeWallet(_guard, signingKey, "0x00000000", hexlify(I.slice(32)), "m", 0, 0, mnemonic, null);
 
-         }
 
-         /**
 
-          *  Creates a new HD Node from %%extendedKey%%.
 
-          *
 
-          *  If the %%extendedKey%% will either have a prefix or ``xpub`` or
 
-          *  ``xpriv``, returning a neutered HD Node ([[HDNodeVoidWallet]])
 
-          *  or full HD Node ([[HDNodeWallet) respectively.
 
-          */
 
-         static fromExtendedKey(extendedKey) {
 
-             const bytes = toBeArray(decodeBase58(extendedKey)); // @TODO: redact
 
-             assertArgument(bytes.length === 82 || encodeBase58Check(bytes.slice(0, 78)) === extendedKey, "invalid extended key", "extendedKey", "[ REDACTED ]");
 
-             const depth = bytes[4];
 
-             const parentFingerprint = hexlify(bytes.slice(5, 9));
 
-             const index = parseInt(hexlify(bytes.slice(9, 13)).substring(2), 16);
 
-             const chainCode = hexlify(bytes.slice(13, 45));
 
-             const key = bytes.slice(45, 78);
 
-             switch (hexlify(bytes.slice(0, 4))) {
 
-                 // Public Key
 
-                 case "0x0488b21e":
 
-                 case "0x043587cf": {
 
-                     const publicKey = hexlify(key);
 
-                     return new HDNodeVoidWallet(_guard, computeAddress(publicKey), publicKey, parentFingerprint, chainCode, null, index, depth, null);
 
-                 }
 
-                 // Private Key
 
-                 case "0x0488ade4":
 
-                 case "0x04358394 ":
 
-                     if (key[0] !== 0) {
 
-                         break;
 
-                     }
 
-                     return new HDNodeWallet(_guard, new SigningKey(key.slice(1)), parentFingerprint, chainCode, null, index, depth, null, null);
 
-             }
 
-             assertArgument(false, "invalid extended key prefix", "extendedKey", "[ REDACTED ]");
 
-         }
 
-         /**
 
-          *  Creates a new random HDNode.
 
-          */
 
-         static createRandom(password, path, wordlist) {
 
-             if (password == null) {
 
-                 password = "";
 
-             }
 
-             if (path == null) {
 
-                 path = defaultPath;
 
-             }
 
-             if (wordlist == null) {
 
-                 wordlist = LangEn.wordlist();
 
-             }
 
-             const mnemonic = Mnemonic.fromEntropy(randomBytes(16), password, wordlist);
 
-             return HDNodeWallet.#fromSeed(mnemonic.computeSeed(), mnemonic).derivePath(path);
 
-         }
 
-         /**
 
-          *  Create an HD Node from %%mnemonic%%.
 
-          */
 
-         static fromMnemonic(mnemonic, path) {
 
-             if (!path) {
 
-                 path = defaultPath;
 
-             }
 
-             return HDNodeWallet.#fromSeed(mnemonic.computeSeed(), mnemonic).derivePath(path);
 
-         }
 
-         /**
 
-          *  Creates an HD Node from a mnemonic %%phrase%%.
 
-          */
 
-         static fromPhrase(phrase, password, path, wordlist) {
 
-             if (password == null) {
 
-                 password = "";
 
-             }
 
-             if (path == null) {
 
-                 path = defaultPath;
 
-             }
 
-             if (wordlist == null) {
 
-                 wordlist = LangEn.wordlist();
 
-             }
 
-             const mnemonic = Mnemonic.fromPhrase(phrase, password, wordlist);
 
-             return HDNodeWallet.#fromSeed(mnemonic.computeSeed(), mnemonic).derivePath(path);
 
-         }
 
-         /**
 
-          *  Creates an HD Node from a %%seed%%.
 
-          */
 
-         static fromSeed(seed) {
 
-             return HDNodeWallet.#fromSeed(seed, null);
 
-         }
 
-     }
 
-     /**
 
-      *  A **HDNodeVoidWallet** cannot sign, but provides access to
 
-      *  the children nodes of a [[link-bip-32]] HD wallet addresses.
 
-      *
 
-      *  The can be created by using an extended ``xpub`` key to
 
-      *  [[HDNodeWallet_fromExtendedKey]] or by
 
-      *  [nuetering](HDNodeWallet-neuter) a [[HDNodeWallet]].
 
-      */
 
-     class HDNodeVoidWallet extends VoidSigner {
 
-         /**
 
-          *  The compressed public key.
 
-          */
 
-         publicKey;
 
-         /**
 
-          *  The fingerprint.
 
-          *
 
-          *  A fingerprint allows quick qay to detect parent and child nodes,
 
-          *  but developers should be prepared to deal with collisions as it
 
-          *  is only 4 bytes.
 
-          */
 
-         fingerprint;
 
-         /**
 
-          *  The parent node fingerprint.
 
-          */
 
-         parentFingerprint;
 
-         /**
 
-          *  The chaincode, which is effectively a public key used
 
-          *  to derive children.
 
-          */
 
-         chainCode;
 
-         /**
 
-          *  The derivation path of this wallet.
 
-          *
 
-          *  Since extended keys do not provider full path details, this
 
-          *  may be ``null``, if instantiated from a source that does not
 
-          *  enocde it.
 
-          */
 
-         path;
 
-         /**
 
-          *  The child index of this wallet. Values over ``2 *\* 31`` indicate
 
-          *  the node is hardened.
 
-          */
 
-         index;
 
-         /**
 
-          *  The depth of this wallet, which is the number of components
 
-          *  in its path.
 
-          */
 
-         depth;
 
-         /**
 
-          *  @private
 
-          */
 
-         constructor(guard, address, publicKey, parentFingerprint, chainCode, path, index, depth, provider) {
 
-             super(address, provider);
 
-             assertPrivate(guard, _guard, "HDNodeVoidWallet");
 
-             defineProperties(this, { publicKey });
 
-             const fingerprint = dataSlice(ripemd160(sha256(publicKey)), 0, 4);
 
-             defineProperties(this, {
 
-                 publicKey, fingerprint, parentFingerprint, chainCode, path, index, depth
 
-             });
 
-         }
 
-         connect(provider) {
 
-             return new HDNodeVoidWallet(_guard, this.address, this.publicKey, this.parentFingerprint, this.chainCode, this.path, this.index, this.depth, provider);
 
-         }
 
-         /**
 
-          *  The extended key.
 
-          *
 
-          *  This key will begin with the prefix ``xpub`` and can be used to
 
-          *  reconstruct this neutered key to derive its children addresses.
 
-          */
 
-         get extendedKey() {
 
-             // We only support the mainnet values for now, but if anyone needs
 
-             // testnet values, let me know. I believe current sentiment is that
 
-             // we should always use mainnet, and use BIP-44 to derive the network
 
-             //   - Mainnet: public=0x0488B21E, private=0x0488ADE4
 
-             //   - Testnet: public=0x043587CF, private=0x04358394
 
-             assert(this.depth < 256, "Depth too deep", "UNSUPPORTED_OPERATION", { operation: "extendedKey" });
 
-             return encodeBase58Check(concat([
 
-                 "0x0488B21E",
 
-                 zpad(this.depth, 1),
 
-                 this.parentFingerprint,
 
-                 zpad(this.index, 4),
 
-                 this.chainCode,
 
-                 this.publicKey,
 
-             ]));
 
-         }
 
-         /**
 
-          *  Returns true if this wallet has a path, providing a Type Guard
 
-          *  that the path is non-null.
 
-          */
 
-         hasPath() { return (this.path != null); }
 
-         /**
 
-          *  Return the child for %%index%%.
 
-          */
 
-         deriveChild(_index) {
 
-             const index = getNumber(_index, "index");
 
-             assertArgument(index <= 0xffffffff, "invalid index", "index", index);
 
-             // Base path
 
-             let path = this.path;
 
-             if (path) {
 
-                 path += "/" + (index & ~HardenedBit);
 
-                 if (index & HardenedBit) {
 
-                     path += "'";
 
-                 }
 
-             }
 
-             const { IR, IL } = ser_I(index, this.chainCode, this.publicKey, null);
 
-             const Ki = SigningKey.addPoints(IL, this.publicKey, true);
 
-             const address = computeAddress(Ki);
 
-             return new HDNodeVoidWallet(_guard, address, Ki, this.fingerprint, hexlify(IR), path, index, this.depth + 1, this.provider);
 
-         }
 
-         /**
 
-          *  Return the signer for %%path%% from this node.
 
-          */
 
-         derivePath(path) {
 
-             return derivePath(this, path);
 
-         }
 
-     }
 
-     /*
 
-     export class HDNodeWalletManager {
 
-         #root: HDNodeWallet;
 
-         constructor(phrase: string, password?: null | string, path?: null | string, locale?: null | Wordlist) {
 
-             if (password == null) { password = ""; }
 
-             if (path == null) { path = "m/44'/60'/0'/0"; }
 
-             if (locale == null) { locale = LangEn.wordlist(); }
 
-             this.#root = HDNodeWallet.fromPhrase(phrase, password, path, locale);
 
-         }
 
-         getSigner(index?: number): HDNodeWallet {
 
-             return this.#root.deriveChild((index == null) ? 0: index);
 
-         }
 
-     }
 
-     */
 
-     /**
 
-      *  Returns the [[link-bip-32]] path for the account at %%index%%.
 
-      *
 
-      *  This is the pattern used by wallets like Ledger.
 
-      *
 
-      *  There is also an [alternate pattern](getIndexedAccountPath) used by
 
-      *  some software.
 
-      */
 
-     function getAccountPath(_index) {
 
-         const index = getNumber(_index, "index");
 
-         assertArgument(index >= 0 && index < HardenedBit, "invalid account index", "index", index);
 
-         return `m/44'/60'/${index}'/0/0`;
 
-     }
 
-     /**
 
-      *  Returns the path using an alternative pattern for deriving accounts,
 
-      *  at %%index%%.
 
-      *
 
-      *  This derivation path uses the //index// component rather than the
 
-      *  //account// component to derive sequential accounts.
 
-      *
 
-      *  This is the pattern used by wallets like MetaMask.
 
-      */
 
-     function getIndexedAccountPath(_index) {
 
-         const index = getNumber(_index, "index");
 
-         assertArgument(index >= 0 && index < HardenedBit, "invalid account index", "index", index);
 
-         return `m/44'/60'/0'/0/${index}`;
 
-     }
 
-     /**
 
-      *  @_subsection: api/wallet:JSON Wallets  [json-wallets]
 
-      */
 
-     /**
 
-      *  Returns true if %%json%% is a valid JSON Crowdsale wallet.
 
-      */
 
-     function isCrowdsaleJson(json) {
 
-         try {
 
-             const data = JSON.parse(json);
 
-             if (data.encseed) {
 
-                 return true;
 
-             }
 
-         }
 
-         catch (error) { }
 
-         return false;
 
-     }
 
-     // See: https://github.com/ethereum/pyethsaletool
 
-     /**
 
-      *  Before Ethereum launched, it was necessary to create a wallet
 
-      *  format for backers to use, which would be used to receive ether
 
-      *  as a reward for contributing to the project.
 
-      *
 
-      *  The [[link-crowdsale]] format is now obsolete, but it is still
 
-      *  useful to support and the additional code is fairly trivial as
 
-      *  all the primitives required are used through core portions of
 
-      *  the library.
 
-      */
 
-     function decryptCrowdsaleJson(json, _password) {
 
-         const data = JSON.parse(json);
 
-         const password = getPassword(_password);
 
-         // Ethereum Address
 
-         const address = getAddress(spelunk(data, "ethaddr:string!"));
 
-         // Encrypted Seed
 
-         const encseed = looseArrayify(spelunk(data, "encseed:string!"));
 
-         assertArgument(encseed && (encseed.length % 16) === 0, "invalid encseed", "json", json);
 
-         const key = getBytes(pbkdf2(password, password, 2000, 32, "sha256")).slice(0, 16);
 
-         const iv = encseed.slice(0, 16);
 
-         const encryptedSeed = encseed.slice(16);
 
-         // Decrypt the seed
 
-         const aesCbc = new CBC(key, iv);
 
-         const seed = pkcs7Strip(getBytes(aesCbc.decrypt(encryptedSeed)));
 
-         // This wallet format is weird... Convert the binary encoded hex to a string.
 
-         let seedHex = "";
 
-         for (let i = 0; i < seed.length; i++) {
 
-             seedHex += String.fromCharCode(seed[i]);
 
-         }
 
-         return { address, privateKey: id(seedHex) };
 
-     }
 
-     function stall(duration) {
 
-         return new Promise((resolve) => { setTimeout(() => { resolve(); }, duration); });
 
-     }
 
-     /**
 
-      *  A **Wallet** manages a single private key which is used to sign
 
-      *  transactions, messages and other common payloads.
 
-      *
 
-      *  This class is generally the main entry point for developers
 
-      *  that wish to use a private key directly, as it can create
 
-      *  instances from a large variety of common sources, including
 
-      *  raw private key, [[link-bip-39]] mnemonics and encrypte JSON
 
-      *  wallets.
 
-      */
 
-     class Wallet extends BaseWallet {
 
-         /**
 
-          *  Create a new wallet for the private %%key%%, optionally connected
 
-          *  to %%provider%%.
 
-          */
 
-         constructor(key, provider) {
 
-             if (typeof (key) === "string" && !key.startsWith("0x")) {
 
-                 key = "0x" + key;
 
-             }
 
-             let signingKey = (typeof (key) === "string") ? new SigningKey(key) : key;
 
-             super(signingKey, provider);
 
-         }
 
-         connect(provider) {
 
-             return new Wallet(this.signingKey, provider);
 
-         }
 
-         /**
 
-          *  Resolves to a [JSON Keystore Wallet](json-wallets) encrypted with
 
-          *  %%password%%.
 
-          *
 
-          *  If %%progressCallback%% is specified, it will receive periodic
 
-          *  updates as the encryption process progreses.
 
-          */
 
-         async encrypt(password, progressCallback) {
 
-             const account = { address: this.address, privateKey: this.privateKey };
 
-             return await encryptKeystoreJson(account, password, { progressCallback });
 
-         }
 
-         /**
 
-          *  Returns a [JSON Keystore Wallet](json-wallets) encryped with
 
-          *  %%password%%.
 
-          *
 
-          *  It is preferred to use the [async version](encrypt) instead,
 
-          *  which allows a [[ProgressCallback]] to keep the user informed.
 
-          *
 
-          *  This method will block the event loop (freezing all UI) until
 
-          *  it is complete, which may be a non-trivial duration.
 
-          */
 
-         encryptSync(password) {
 
-             const account = { address: this.address, privateKey: this.privateKey };
 
-             return encryptKeystoreJsonSync(account, password);
 
-         }
 
-         static #fromAccount(account) {
 
-             assertArgument(account, "invalid JSON wallet", "json", "[ REDACTED ]");
 
-             if ("mnemonic" in account && account.mnemonic && account.mnemonic.locale === "en") {
 
-                 const mnemonic = Mnemonic.fromEntropy(account.mnemonic.entropy);
 
-                 const wallet = HDNodeWallet.fromMnemonic(mnemonic, account.mnemonic.path);
 
-                 if (wallet.address === account.address && wallet.privateKey === account.privateKey) {
 
-                     return wallet;
 
-                 }
 
-                 console.log("WARNING: JSON mismatch address/privateKey != mnemonic; fallback onto private key");
 
-             }
 
-             const wallet = new Wallet(account.privateKey);
 
-             assertArgument(wallet.address === account.address, "address/privateKey mismatch", "json", "[ REDACTED ]");
 
-             return wallet;
 
-         }
 
-         /**
 
-          *  Creates (asynchronously) a **Wallet** by decrypting the %%json%%
 
-          *  with %%password%%.
 
-          *
 
-          *  If %%progress%% is provided, it is called periodically during
 
-          *  decryption so that any UI can be updated.
 
-          */
 
-         static async fromEncryptedJson(json, password, progress) {
 
-             let account = null;
 
-             if (isKeystoreJson(json)) {
 
-                 account = await decryptKeystoreJson(json, password, progress);
 
-             }
 
-             else if (isCrowdsaleJson(json)) {
 
-                 if (progress) {
 
-                     progress(0);
 
-                     await stall(0);
 
-                 }
 
-                 account = decryptCrowdsaleJson(json, password);
 
-                 if (progress) {
 
-                     progress(1);
 
-                     await stall(0);
 
-                 }
 
-             }
 
-             return Wallet.#fromAccount(account);
 
-         }
 
-         /**
 
-          *  Creates a **Wallet** by decrypting the %%json%% with %%password%%.
 
-          *
 
-          *  The [[fromEncryptedJson]] method is preferred, as this method
 
-          *  will lock up and freeze the UI during decryption, which may take
 
-          *  some time.
 
-          */
 
-         static fromEncryptedJsonSync(json, password) {
 
-             let account = null;
 
-             if (isKeystoreJson(json)) {
 
-                 account = decryptKeystoreJsonSync(json, password);
 
-             }
 
-             else if (isCrowdsaleJson(json)) {
 
-                 account = decryptCrowdsaleJson(json, password);
 
-             }
 
-             else {
 
-                 assertArgument(false, "invalid JSON wallet", "json", "[ REDACTED ]");
 
-             }
 
-             return Wallet.#fromAccount(account);
 
-         }
 
-         /**
 
-          *  Creates a new random [[HDNodeWallet]] using the available
 
-          *  [cryptographic random source](randomBytes).
 
-          *
 
-          *  If there is no crytographic random source, this will throw.
 
-          */
 
-         static createRandom(provider) {
 
-             const wallet = HDNodeWallet.createRandom();
 
-             if (provider) {
 
-                 return wallet.connect(provider);
 
-             }
 
-             return wallet;
 
-         }
 
-         /**
 
-          *  Creates a [[HDNodeWallet]] for %%phrase%%.
 
-          */
 
-         static fromPhrase(phrase, provider) {
 
-             const wallet = HDNodeWallet.fromPhrase(phrase);
 
-             if (provider) {
 
-                 return wallet.connect(provider);
 
-             }
 
-             return wallet;
 
-         }
 
-     }
 
-     const Base64 = ")!@#$%^&*(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     function decodeBits(width, data) {
 
-         const maxValue = (1 << width) - 1;
 
-         const result = [];
 
-         let accum = 0, bits = 0, flood = 0;
 
-         for (let i = 0; i < data.length; i++) {
 
-             // Accumulate 6 bits of data
 
-             accum = ((accum << 6) | Base64.indexOf(data[i]));
 
-             bits += 6;
 
-             // While we have enough for a word...
 
-             while (bits >= width) {
 
-                 // ...read the word
 
-                 const value = (accum >> (bits - width));
 
-                 accum &= (1 << (bits - width)) - 1;
 
-                 bits -= width;
 
-                 // A value of 0 indicates we exceeded maxValue, it
 
-                 // floods over into the next value
 
-                 if (value === 0) {
 
-                     flood += maxValue;
 
-                 }
 
-                 else {
 
-                     result.push(value + flood);
 
-                     flood = 0;
 
-                 }
 
-             }
 
-         }
 
-         return result;
 
-     }
 
-     /**
 
-      *  @_ignore
 
-      */
 
-     function decodeOwlA(data, accents) {
 
-         let words = decodeOwl(data).join(",");
 
-         // Inject the accents
 
-         accents.split(/,/g).forEach((accent) => {
 
-             const match = accent.match(/^([a-z]*)([0-9]+)([0-9])(.*)$/);
 
-             assertArgument(match !== null, "internal error parsing accents", "accents", accents);
 
-             let posOffset = 0;
 
-             const positions = decodeBits(parseInt(match[3]), match[4]);
 
-             const charCode = parseInt(match[2]);
 
-             const regex = new RegExp(`([${match[1]}])`, "g");
 
-             words = words.replace(regex, (all, letter) => {
 
-                 const rem = --positions[posOffset];
 
-                 if (rem === 0) {
 
-                     letter = String.fromCharCode(letter.charCodeAt(0), charCode);
 
-                     posOffset++;
 
-                 }
 
-                 return letter;
 
-             });
 
-         });
 
-         return words.split(",");
 
-     }
 
-     /**
 
-      *  An OWL-A format Wordlist extends the OWL format to add an
 
-      *  overlay onto an OWL format Wordlist to support diacritic
 
-      *  marks.
 
-      *
 
-      *  This class is generally not useful to most developers as
 
-      *  it is used mainly internally to keep Wordlists for languages
 
-      *  based on latin-1 small.
 
-      *
 
-      *  If necessary, there are tools within the ``generation/`` folder
 
-      *  to create the necessary data.
 
-      */
 
-     class WordlistOwlA extends WordlistOwl {
 
-         #accent;
 
-         /**
 
-          *  Creates a new Wordlist for %%locale%% using the OWLA %%data%%
 
-          *  and %%accent%% data and validated against the %%checksum%%.
 
-          */
 
-         constructor(locale, data, accent, checksum) {
 
-             super(locale, data, checksum);
 
-             this.#accent = accent;
 
-         }
 
-         /**
 
-          *  The OWLA-encoded accent data.
 
-          */
 
-         get _accent() { return this.#accent; }
 
-         /**
 
-          *  Decode all the words for the wordlist.
 
-          */
 
-         _decodeWords() {
 
-             return decodeOwlA(this._data, this._accent);
 
-         }
 
-     }
 
-     const wordlists = {
 
-         en: LangEn.wordlist(),
 
-     };
 
-     /////////////////////////////
 
-     //
 
-     // dummy change; to pick-up ws security issue changes
 
-     var ethers = /*#__PURE__*/Object.freeze({
 
-         __proto__: null,
 
-         AbiCoder: AbiCoder,
 
-         AbstractProvider: AbstractProvider,
 
-         AbstractSigner: AbstractSigner,
 
-         AlchemyProvider: AlchemyProvider,
 
-         AnkrProvider: AnkrProvider,
 
-         BaseContract: BaseContract,
 
-         BaseWallet: BaseWallet,
 
-         Block: Block,
 
-         BrowserProvider: BrowserProvider,
 
-         ChainstackProvider: ChainstackProvider,
 
-         CloudflareProvider: CloudflareProvider,
 
-         ConstructorFragment: ConstructorFragment,
 
-         Contract: Contract,
 
-         ContractEventPayload: ContractEventPayload,
 
-         ContractFactory: ContractFactory,
 
-         ContractTransactionReceipt: ContractTransactionReceipt,
 
-         ContractTransactionResponse: ContractTransactionResponse,
 
-         ContractUnknownEventPayload: ContractUnknownEventPayload,
 
-         EnsPlugin: EnsPlugin,
 
-         EnsResolver: EnsResolver,
 
-         ErrorDescription: ErrorDescription,
 
-         ErrorFragment: ErrorFragment,
 
-         EtherSymbol: EtherSymbol,
 
-         EtherscanPlugin: EtherscanPlugin,
 
-         EtherscanProvider: EtherscanProvider,
 
-         EventFragment: EventFragment,
 
-         EventLog: EventLog,
 
-         EventPayload: EventPayload,
 
-         FallbackFragment: FallbackFragment,
 
-         FallbackProvider: FallbackProvider,
 
-         FeeData: FeeData,
 
-         FeeDataNetworkPlugin: FeeDataNetworkPlugin,
 
-         FetchCancelSignal: FetchCancelSignal,
 
-         FetchRequest: FetchRequest,
 
-         FetchResponse: FetchResponse,
 
-         FetchUrlFeeDataNetworkPlugin: FetchUrlFeeDataNetworkPlugin,
 
-         FixedNumber: FixedNumber,
 
-         Fragment: Fragment,
 
-         FunctionFragment: FunctionFragment,
 
-         GasCostPlugin: GasCostPlugin,
 
-         HDNodeVoidWallet: HDNodeVoidWallet,
 
-         HDNodeWallet: HDNodeWallet,
 
-         Indexed: Indexed,
 
-         InfuraProvider: InfuraProvider,
 
-         InfuraWebSocketProvider: InfuraWebSocketProvider,
 
-         Interface: Interface,
 
-         IpcSocketProvider: IpcSocketProvider,
 
-         JsonRpcApiProvider: JsonRpcApiProvider,
 
-         JsonRpcProvider: JsonRpcProvider,
 
-         JsonRpcSigner: JsonRpcSigner,
 
-         LangEn: LangEn,
 
-         Log: Log,
 
-         LogDescription: LogDescription,
 
-         MaxInt256: MaxInt256,
 
-         MaxUint256: MaxUint256,
 
-         MessagePrefix: MessagePrefix,
 
-         MinInt256: MinInt256,
 
-         Mnemonic: Mnemonic,
 
-         MulticoinProviderPlugin: MulticoinProviderPlugin,
 
-         N: N$1,
 
-         NamedFragment: NamedFragment,
 
-         Network: Network,
 
-         NetworkPlugin: NetworkPlugin,
 
-         NonceManager: NonceManager,
 
-         ParamType: ParamType,
 
-         PocketProvider: PocketProvider,
 
-         QuickNodeProvider: QuickNodeProvider,
 
-         Result: Result,
 
-         Signature: Signature,
 
-         SigningKey: SigningKey,
 
-         SocketBlockSubscriber: SocketBlockSubscriber,
 
-         SocketEventSubscriber: SocketEventSubscriber,
 
-         SocketPendingSubscriber: SocketPendingSubscriber,
 
-         SocketProvider: SocketProvider,
 
-         SocketSubscriber: SocketSubscriber,
 
-         StructFragment: StructFragment,
 
-         Transaction: Transaction,
 
-         TransactionDescription: TransactionDescription,
 
-         TransactionReceipt: TransactionReceipt,
 
-         TransactionResponse: TransactionResponse,
 
-         Typed: Typed,
 
-         TypedDataEncoder: TypedDataEncoder,
 
-         UndecodedEventLog: UndecodedEventLog,
 
-         UnmanagedSubscriber: UnmanagedSubscriber,
 
-         Utf8ErrorFuncs: Utf8ErrorFuncs,
 
-         VoidSigner: VoidSigner,
 
-         Wallet: Wallet,
 
-         WebSocketProvider: WebSocketProvider,
 
-         WeiPerEther: WeiPerEther,
 
-         Wordlist: Wordlist,
 
-         WordlistOwl: WordlistOwl,
 
-         WordlistOwlA: WordlistOwlA,
 
-         ZeroAddress: ZeroAddress,
 
-         ZeroHash: ZeroHash,
 
-         accessListify: accessListify,
 
-         assert: assert,
 
-         assertArgument: assertArgument,
 
-         assertArgumentCount: assertArgumentCount,
 
-         assertNormalize: assertNormalize,
 
-         assertPrivate: assertPrivate,
 
-         checkResultErrors: checkResultErrors,
 
-         computeAddress: computeAddress,
 
-         computeHmac: computeHmac,
 
-         concat: concat,
 
-         copyRequest: copyRequest,
 
-         dataLength: dataLength,
 
-         dataSlice: dataSlice,
 
-         decodeBase58: decodeBase58,
 
-         decodeBase64: decodeBase64,
 
-         decodeBytes32String: decodeBytes32String,
 
-         decodeRlp: decodeRlp,
 
-         decryptCrowdsaleJson: decryptCrowdsaleJson,
 
-         decryptKeystoreJson: decryptKeystoreJson,
 
-         decryptKeystoreJsonSync: decryptKeystoreJsonSync,
 
-         defaultPath: defaultPath,
 
-         defineProperties: defineProperties,
 
-         dnsEncode: dnsEncode,
 
-         encodeBase58: encodeBase58,
 
-         encodeBase64: encodeBase64,
 
-         encodeBytes32String: encodeBytes32String,
 
-         encodeRlp: encodeRlp,
 
-         encryptKeystoreJson: encryptKeystoreJson,
 
-         encryptKeystoreJsonSync: encryptKeystoreJsonSync,
 
-         ensNormalize: ensNormalize,
 
-         formatEther: formatEther,
 
-         formatUnits: formatUnits,
 
-         fromTwos: fromTwos,
 
-         getAccountPath: getAccountPath,
 
-         getAddress: getAddress,
 
-         getBigInt: getBigInt,
 
-         getBytes: getBytes,
 
-         getBytesCopy: getBytesCopy,
 
-         getCreate2Address: getCreate2Address,
 
-         getCreateAddress: getCreateAddress,
 
-         getDefaultProvider: getDefaultProvider,
 
-         getIcapAddress: getIcapAddress,
 
-         getIndexedAccountPath: getIndexedAccountPath,
 
-         getNumber: getNumber,
 
-         getUint: getUint,
 
-         hashMessage: hashMessage,
 
-         hexlify: hexlify,
 
-         id: id,
 
-         isAddress: isAddress,
 
-         isAddressable: isAddressable,
 
-         isBytesLike: isBytesLike,
 
-         isCallException: isCallException,
 
-         isCrowdsaleJson: isCrowdsaleJson,
 
-         isError: isError,
 
-         isHexString: isHexString,
 
-         isKeystoreJson: isKeystoreJson,
 
-         isValidName: isValidName,
 
-         keccak256: keccak256,
 
-         lock: lock,
 
-         makeError: makeError,
 
-         mask: mask,
 
-         namehash: namehash,
 
-         parseEther: parseEther,
 
-         parseUnits: parseUnits$1,
 
-         pbkdf2: pbkdf2,
 
-         randomBytes: randomBytes,
 
-         recoverAddress: recoverAddress,
 
-         resolveAddress: resolveAddress,
 
-         resolveProperties: resolveProperties,
 
-         ripemd160: ripemd160,
 
-         scrypt: scrypt,
 
-         scryptSync: scryptSync,
 
-         sha256: sha256,
 
-         sha512: sha512,
 
-         showThrottleMessage: showThrottleMessage,
 
-         solidityPacked: solidityPacked,
 
-         solidityPackedKeccak256: solidityPackedKeccak256,
 
-         solidityPackedSha256: solidityPackedSha256,
 
-         stripZerosLeft: stripZerosLeft,
 
-         toBeArray: toBeArray,
 
-         toBeHex: toBeHex,
 
-         toBigInt: toBigInt,
 
-         toNumber: toNumber,
 
-         toQuantity: toQuantity,
 
-         toTwos: toTwos,
 
-         toUtf8Bytes: toUtf8Bytes,
 
-         toUtf8CodePoints: toUtf8CodePoints,
 
-         toUtf8String: toUtf8String,
 
-         uuidV4: uuidV4,
 
-         verifyMessage: verifyMessage,
 
-         verifyTypedData: verifyTypedData,
 
-         version: version,
 
-         wordlists: wordlists,
 
-         zeroPadBytes: zeroPadBytes,
 
-         zeroPadValue: zeroPadValue
 
-     });
 
-     exports.AbiCoder = AbiCoder;
 
-     exports.AbstractProvider = AbstractProvider;
 
-     exports.AbstractSigner = AbstractSigner;
 
-     exports.AlchemyProvider = AlchemyProvider;
 
-     exports.AnkrProvider = AnkrProvider;
 
-     exports.BaseContract = BaseContract;
 
-     exports.BaseWallet = BaseWallet;
 
-     exports.Block = Block;
 
-     exports.BrowserProvider = BrowserProvider;
 
-     exports.ChainstackProvider = ChainstackProvider;
 
-     exports.CloudflareProvider = CloudflareProvider;
 
-     exports.ConstructorFragment = ConstructorFragment;
 
-     exports.Contract = Contract;
 
-     exports.ContractEventPayload = ContractEventPayload;
 
-     exports.ContractFactory = ContractFactory;
 
-     exports.ContractTransactionReceipt = ContractTransactionReceipt;
 
-     exports.ContractTransactionResponse = ContractTransactionResponse;
 
-     exports.ContractUnknownEventPayload = ContractUnknownEventPayload;
 
-     exports.EnsPlugin = EnsPlugin;
 
-     exports.EnsResolver = EnsResolver;
 
-     exports.ErrorDescription = ErrorDescription;
 
-     exports.ErrorFragment = ErrorFragment;
 
-     exports.EtherSymbol = EtherSymbol;
 
-     exports.EtherscanPlugin = EtherscanPlugin;
 
-     exports.EtherscanProvider = EtherscanProvider;
 
-     exports.EventFragment = EventFragment;
 
-     exports.EventLog = EventLog;
 
-     exports.EventPayload = EventPayload;
 
-     exports.FallbackFragment = FallbackFragment;
 
-     exports.FallbackProvider = FallbackProvider;
 
-     exports.FeeData = FeeData;
 
-     exports.FeeDataNetworkPlugin = FeeDataNetworkPlugin;
 
-     exports.FetchCancelSignal = FetchCancelSignal;
 
-     exports.FetchRequest = FetchRequest;
 
-     exports.FetchResponse = FetchResponse;
 
-     exports.FetchUrlFeeDataNetworkPlugin = FetchUrlFeeDataNetworkPlugin;
 
-     exports.FixedNumber = FixedNumber;
 
-     exports.Fragment = Fragment;
 
-     exports.FunctionFragment = FunctionFragment;
 
-     exports.GasCostPlugin = GasCostPlugin;
 
-     exports.HDNodeVoidWallet = HDNodeVoidWallet;
 
-     exports.HDNodeWallet = HDNodeWallet;
 
-     exports.Indexed = Indexed;
 
-     exports.InfuraProvider = InfuraProvider;
 
-     exports.InfuraWebSocketProvider = InfuraWebSocketProvider;
 
-     exports.Interface = Interface;
 
-     exports.IpcSocketProvider = IpcSocketProvider;
 
-     exports.JsonRpcApiProvider = JsonRpcApiProvider;
 
-     exports.JsonRpcProvider = JsonRpcProvider;
 
-     exports.JsonRpcSigner = JsonRpcSigner;
 
-     exports.LangEn = LangEn;
 
-     exports.Log = Log;
 
-     exports.LogDescription = LogDescription;
 
-     exports.MaxInt256 = MaxInt256;
 
-     exports.MaxUint256 = MaxUint256;
 
-     exports.MessagePrefix = MessagePrefix;
 
-     exports.MinInt256 = MinInt256;
 
-     exports.Mnemonic = Mnemonic;
 
-     exports.MulticoinProviderPlugin = MulticoinProviderPlugin;
 
-     exports.N = N$1;
 
-     exports.NamedFragment = NamedFragment;
 
-     exports.Network = Network;
 
-     exports.NetworkPlugin = NetworkPlugin;
 
-     exports.NonceManager = NonceManager;
 
-     exports.ParamType = ParamType;
 
-     exports.PocketProvider = PocketProvider;
 
-     exports.QuickNodeProvider = QuickNodeProvider;
 
-     exports.Result = Result;
 
-     exports.Signature = Signature;
 
-     exports.SigningKey = SigningKey;
 
-     exports.SocketBlockSubscriber = SocketBlockSubscriber;
 
-     exports.SocketEventSubscriber = SocketEventSubscriber;
 
-     exports.SocketPendingSubscriber = SocketPendingSubscriber;
 
-     exports.SocketProvider = SocketProvider;
 
-     exports.SocketSubscriber = SocketSubscriber;
 
-     exports.StructFragment = StructFragment;
 
-     exports.Transaction = Transaction;
 
-     exports.TransactionDescription = TransactionDescription;
 
-     exports.TransactionReceipt = TransactionReceipt;
 
-     exports.TransactionResponse = TransactionResponse;
 
-     exports.Typed = Typed;
 
-     exports.TypedDataEncoder = TypedDataEncoder;
 
-     exports.UndecodedEventLog = UndecodedEventLog;
 
-     exports.UnmanagedSubscriber = UnmanagedSubscriber;
 
-     exports.Utf8ErrorFuncs = Utf8ErrorFuncs;
 
-     exports.VoidSigner = VoidSigner;
 
-     exports.Wallet = Wallet;
 
-     exports.WebSocketProvider = WebSocketProvider;
 
-     exports.WeiPerEther = WeiPerEther;
 
-     exports.Wordlist = Wordlist;
 
-     exports.WordlistOwl = WordlistOwl;
 
-     exports.WordlistOwlA = WordlistOwlA;
 
-     exports.ZeroAddress = ZeroAddress;
 
-     exports.ZeroHash = ZeroHash;
 
-     exports.accessListify = accessListify;
 
-     exports.assert = assert;
 
-     exports.assertArgument = assertArgument;
 
-     exports.assertArgumentCount = assertArgumentCount;
 
-     exports.assertNormalize = assertNormalize;
 
-     exports.assertPrivate = assertPrivate;
 
-     exports.checkResultErrors = checkResultErrors;
 
-     exports.computeAddress = computeAddress;
 
-     exports.computeHmac = computeHmac;
 
-     exports.concat = concat;
 
-     exports.copyRequest = copyRequest;
 
-     exports.dataLength = dataLength;
 
-     exports.dataSlice = dataSlice;
 
-     exports.decodeBase58 = decodeBase58;
 
-     exports.decodeBase64 = decodeBase64;
 
-     exports.decodeBytes32String = decodeBytes32String;
 
-     exports.decodeRlp = decodeRlp;
 
-     exports.decryptCrowdsaleJson = decryptCrowdsaleJson;
 
-     exports.decryptKeystoreJson = decryptKeystoreJson;
 
-     exports.decryptKeystoreJsonSync = decryptKeystoreJsonSync;
 
-     exports.defaultPath = defaultPath;
 
-     exports.defineProperties = defineProperties;
 
-     exports.dnsEncode = dnsEncode;
 
-     exports.encodeBase58 = encodeBase58;
 
-     exports.encodeBase64 = encodeBase64;
 
-     exports.encodeBytes32String = encodeBytes32String;
 
-     exports.encodeRlp = encodeRlp;
 
-     exports.encryptKeystoreJson = encryptKeystoreJson;
 
-     exports.encryptKeystoreJsonSync = encryptKeystoreJsonSync;
 
-     exports.ensNormalize = ensNormalize;
 
-     exports.ethers = ethers;
 
-     exports.formatEther = formatEther;
 
-     exports.formatUnits = formatUnits;
 
-     exports.fromTwos = fromTwos;
 
-     exports.getAccountPath = getAccountPath;
 
-     exports.getAddress = getAddress;
 
-     exports.getBigInt = getBigInt;
 
-     exports.getBytes = getBytes;
 
-     exports.getBytesCopy = getBytesCopy;
 
-     exports.getCreate2Address = getCreate2Address;
 
-     exports.getCreateAddress = getCreateAddress;
 
-     exports.getDefaultProvider = getDefaultProvider;
 
-     exports.getIcapAddress = getIcapAddress;
 
-     exports.getIndexedAccountPath = getIndexedAccountPath;
 
-     exports.getNumber = getNumber;
 
-     exports.getUint = getUint;
 
-     exports.hashMessage = hashMessage;
 
-     exports.hexlify = hexlify;
 
-     exports.id = id;
 
-     exports.isAddress = isAddress;
 
-     exports.isAddressable = isAddressable;
 
-     exports.isBytesLike = isBytesLike;
 
-     exports.isCallException = isCallException;
 
-     exports.isCrowdsaleJson = isCrowdsaleJson;
 
-     exports.isError = isError;
 
-     exports.isHexString = isHexString;
 
-     exports.isKeystoreJson = isKeystoreJson;
 
-     exports.isValidName = isValidName;
 
-     exports.keccak256 = keccak256;
 
-     exports.lock = lock;
 
-     exports.makeError = makeError;
 
-     exports.mask = mask;
 
-     exports.namehash = namehash;
 
-     exports.parseEther = parseEther;
 
-     exports.parseUnits = parseUnits$1;
 
-     exports.pbkdf2 = pbkdf2;
 
-     exports.randomBytes = randomBytes;
 
-     exports.recoverAddress = recoverAddress;
 
-     exports.resolveAddress = resolveAddress;
 
-     exports.resolveProperties = resolveProperties;
 
-     exports.ripemd160 = ripemd160;
 
-     exports.scrypt = scrypt;
 
-     exports.scryptSync = scryptSync;
 
-     exports.sha256 = sha256;
 
-     exports.sha512 = sha512;
 
-     exports.showThrottleMessage = showThrottleMessage;
 
-     exports.solidityPacked = solidityPacked;
 
-     exports.solidityPackedKeccak256 = solidityPackedKeccak256;
 
-     exports.solidityPackedSha256 = solidityPackedSha256;
 
-     exports.stripZerosLeft = stripZerosLeft;
 
-     exports.toBeArray = toBeArray;
 
-     exports.toBeHex = toBeHex;
 
-     exports.toBigInt = toBigInt;
 
-     exports.toNumber = toNumber;
 
-     exports.toQuantity = toQuantity;
 
-     exports.toTwos = toTwos;
 
-     exports.toUtf8Bytes = toUtf8Bytes;
 
-     exports.toUtf8CodePoints = toUtf8CodePoints;
 
-     exports.toUtf8String = toUtf8String;
 
-     exports.uuidV4 = uuidV4;
 
-     exports.verifyMessage = verifyMessage;
 
-     exports.verifyTypedData = verifyTypedData;
 
-     exports.version = version;
 
-     exports.wordlists = wordlists;
 
-     exports.zeroPadBytes = zeroPadBytes;
 
-     exports.zeroPadValue = zeroPadValue;
 
- }));
 
- //# sourceMappingURL=ethers.umd.js.map
 
 
  |