diff --git a/indexer/coverage/clover.xml b/indexer/coverage/clover.xml new file mode 100644 index 00000000..807a93aa --- /dev/null +++ b/indexer/coverage/clover.xml @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indexer/coverage/coverage-final.json b/indexer/coverage/coverage-final.json new file mode 100644 index 00000000..f867d044 --- /dev/null +++ b/indexer/coverage/coverage-final.json @@ -0,0 +1,12 @@ +{"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/app.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/app.ts","statementMap":{"0":{"start":{"line":10,"column":14},"end":{"line":10,"column":23}},"1":{"start":{"line":12,"column":2},"end":{"line":12,"column":26}},"2":{"start":{"line":14,"column":2},"end":{"line":14,"column":39}},"3":{"start":{"line":15,"column":2},"end":{"line":15,"column":38}},"4":{"start":{"line":16,"column":2},"end":{"line":16,"column":33}},"5":{"start":{"line":17,"column":2},"end":{"line":17,"column":36}},"6":{"start":{"line":18,"column":2},"end":{"line":18,"column":34}},"7":{"start":{"line":20,"column":2},"end":{"line":22,"column":5}},"8":{"start":{"line":21,"column":4},"end":{"line":21,"column":31}},"9":{"start":{"line":24,"column":2},"end":{"line":24,"column":13}}},"fnMap":{"0":{"name":"createApp","decl":{"start":{"line":9,"column":16},"end":{"line":9,"column":25}},"loc":{"start":{"line":9,"column":47},"end":{"line":25,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":20,"column":21},"end":{"line":20,"column":22}},"loc":{"start":{"line":20,"column":35},"end":{"line":22,"column":3}}}},"branchMap":{},"s":{"0":42,"1":42,"2":42,"3":42,"4":42,"5":42,"6":42,"7":42,"8":0,"9":42},"f":{"0":42,"1":0},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/config.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/config.ts","statementMap":{"0":{"start":{"line":1,"column":22},"end":{"line":7,"column":2}}},"fnMap":{},"branchMap":{"0":{"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":43}},"type":"binary-expr","locations":[{"start":{"line":2,"column":17},"end":{"line":2,"column":33}},{"start":{"line":2,"column":37},"end":{"line":2,"column":43}}]},"1":{"loc":{"start":{"line":3,"column":10},"end":{"line":3,"column":47}},"type":"binary-expr","locations":[{"start":{"line":3,"column":10},"end":{"line":3,"column":29}},{"start":{"line":3,"column":33},"end":{"line":3,"column":47}}]},"2":{"loc":{"start":{"line":4,"column":23},"end":{"line":4,"column":58}},"type":"binary-expr","locations":[{"start":{"line":4,"column":23},"end":{"line":4,"column":47}},{"start":{"line":4,"column":51},"end":{"line":4,"column":58}}]}},"s":{"0":0},"f":{},"b":{"0":[0,0],"1":[0,0],"2":[0,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/events.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/events.ts","statementMap":{"0":{"start":{"line":17,"column":17},"end":{"line":17,"column":25}},"1":{"start":{"line":19,"column":2},"end":{"line":79,"column":5}},"2":{"start":{"line":20,"column":20},"end":{"line":20,"column":47}},"3":{"start":{"line":21,"column":21},"end":{"line":21,"column":58}},"4":{"start":{"line":22,"column":17},"end":{"line":22,"column":75}},"5":{"start":{"line":23,"column":21},"end":{"line":23,"column":84}},"6":{"start":{"line":24,"column":19},"end":{"line":24,"column":40}},"7":{"start":{"line":26,"column":4},"end":{"line":29,"column":5}},"8":{"start":{"line":27,"column":6},"end":{"line":27,"column":71}},"9":{"start":{"line":28,"column":6},"end":{"line":28,"column":13}},"10":{"start":{"line":31,"column":33},"end":{"line":31,"column":86}},"11":{"start":{"line":32,"column":26},"end":{"line":32,"column":53}},"12":{"start":{"line":34,"column":4},"end":{"line":39,"column":5}},"13":{"start":{"line":35,"column":20},"end":{"line":35,"column":39}},"14":{"start":{"line":36,"column":27},"end":{"line":36,"column":57}},"15":{"start":{"line":36,"column":43},"end":{"line":36,"column":46}},"16":{"start":{"line":37,"column":6},"end":{"line":37,"column":59}},"17":{"start":{"line":38,"column":6},"end":{"line":38,"column":28}},"18":{"start":{"line":41,"column":24},"end":{"line":41,"column":88}},"19":{"start":{"line":44,"column":23},"end":{"line":49,"column":6}},"20":{"start":{"line":50,"column":21},"end":{"line":50,"column":79}},"21":{"start":{"line":51,"column":18},"end":{"line":51,"column":47}},"22":{"start":{"line":54,"column":24},"end":{"line":61,"column":6}},"23":{"start":{"line":62,"column":17},"end":{"line":62,"column":87}},"24":{"start":{"line":64,"column":19},"end":{"line":71,"column":7}},"25":{"start":{"line":64,"column":34},"end":{"line":71,"column":6}},"26":{"start":{"line":73,"column":4},"end":{"line":78,"column":7}},"27":{"start":{"line":81,"column":2},"end":{"line":81,"column":16}}},"fnMap":{"0":{"name":"createEventsRouter","decl":{"start":{"line":16,"column":16},"end":{"line":16,"column":34}},"loc":{"start":{"line":16,"column":56},"end":{"line":82,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":19,"column":24},"end":{"line":19,"column":25}},"loc":{"start":{"line":19,"column":37},"end":{"line":79,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":36,"column":37},"end":{"line":36,"column":40}},"loc":{"start":{"line":36,"column":43},"end":{"line":36,"column":46}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":64,"column":28},"end":{"line":64,"column":29}},"loc":{"start":{"line":64,"column":34},"end":{"line":71,"column":6}}}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":38},"end":{"line":22,"column":69}},"type":"binary-expr","locations":[{"start":{"line":22,"column":38},"end":{"line":22,"column":62}},{"start":{"line":22,"column":66},"end":{"line":22,"column":69}}]},"1":{"loc":{"start":{"line":23,"column":42},"end":{"line":23,"column":78}},"type":"binary-expr","locations":[{"start":{"line":23,"column":42},"end":{"line":23,"column":70}},{"start":{"line":23,"column":74},"end":{"line":23,"column":78}}]},"2":{"loc":{"start":{"line":26,"column":4},"end":{"line":29,"column":5}},"type":"if","locations":[{"start":{"line":26,"column":4},"end":{"line":29,"column":5}}]},"3":{"loc":{"start":{"line":34,"column":4},"end":{"line":39,"column":5}},"type":"if","locations":[{"start":{"line":34,"column":4},"end":{"line":39,"column":5}}]},"4":{"loc":{"start":{"line":41,"column":24},"end":{"line":41,"column":88}},"type":"cond-expr","locations":[{"start":{"line":41,"column":48},"end":{"line":41,"column":83}},{"start":{"line":41,"column":86},"end":{"line":41,"column":88}}]},"5":{"loc":{"start":{"line":51,"column":18},"end":{"line":51,"column":47}},"type":"cond-expr","locations":[{"start":{"line":51,"column":29},"end":{"line":51,"column":43}},{"start":{"line":51,"column":46},"end":{"line":51,"column":47}}]},"6":{"loc":{"start":{"line":70,"column":23},"end":{"line":70,"column":37}},"type":"binary-expr","locations":[{"start":{"line":70,"column":23},"end":{"line":70,"column":29}},{"start":{"line":70,"column":33},"end":{"line":70,"column":37}}]}},"s":{"0":42,"1":42,"2":5,"3":5,"4":5,"5":5,"6":5,"7":5,"8":1,"9":1,"10":4,"11":4,"12":4,"13":1,"14":1,"15":1,"16":1,"17":1,"18":4,"19":4,"20":4,"21":4,"22":4,"23":4,"24":4,"25":6,"26":4,"27":42},"f":{"0":42,"1":5,"2":1,"3":6},"b":{"0":[5,4],"1":[5,4],"2":[1],"3":[1],"4":[4,0],"5":[4,0],"6":[6,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/invoices.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/invoices.ts","statementMap":{"0":{"start":{"line":57,"column":14},"end":{"line":57,"column":43}},"1":{"start":{"line":58,"column":26},"end":{"line":58,"column":39}},"2":{"start":{"line":59,"column":2},"end":{"line":59,"column":37}},"3":{"start":{"line":59,"column":28},"end":{"line":59,"column":37}},"4":{"start":{"line":60,"column":23},"end":{"line":60,"column":55}},"5":{"start":{"line":61,"column":2},"end":{"line":61,"column":57}},"6":{"start":{"line":65,"column":17},"end":{"line":65,"column":25}},"7":{"start":{"line":67,"column":2},"end":{"line":131,"column":5}},"8":{"start":{"line":68,"column":22},"end":{"line":68,"column":49}},"9":{"start":{"line":69,"column":4},"end":{"line":72,"column":5}},"10":{"start":{"line":70,"column":6},"end":{"line":70,"column":60}},"11":{"start":{"line":71,"column":6},"end":{"line":71,"column":13}},"12":{"start":{"line":74,"column":20},"end":{"line":76,"column":47}},"13":{"start":{"line":78,"column":4},"end":{"line":81,"column":5}},"14":{"start":{"line":79,"column":6},"end":{"line":79,"column":59}},"15":{"start":{"line":80,"column":6},"end":{"line":80,"column":13}},"16":{"start":{"line":83,"column":22},"end":{"line":85,"column":35}},"17":{"start":{"line":87,"column":30},"end":{"line":89,"column":null}},"18":{"start":{"line":92,"column":25},"end":{"line":92,"column":61}},"19":{"start":{"line":93,"column":23},"end":{"line":93,"column":57}},"20":{"start":{"line":95,"column":6},"end":{"line":95,"column":73}},"21":{"start":{"line":97,"column":16},"end":{"line":97,"column":45}},"22":{"start":{"line":98,"column":28},"end":{"line":100,"column":null}},"23":{"start":{"line":103,"column":38},"end":{"line":128,"column":6}},"24":{"start":{"line":122,"column":36},"end":{"line":127,"column":8}},"25":{"start":{"line":130,"column":4},"end":{"line":130,"column":23}},"26":{"start":{"line":133,"column":2},"end":{"line":230,"column":5}},"27":{"start":{"line":134,"column":4},"end":{"line":134,"column":49}},"28":{"start":{"line":136,"column":18},"end":{"line":136,"column":55}},"29":{"start":{"line":137,"column":18},"end":{"line":137,"column":55}},"30":{"start":{"line":138,"column":22},"end":{"line":138,"column":63}},"31":{"start":{"line":140,"column":17},"end":{"line":140,"column":75}},"32":{"start":{"line":141,"column":21},"end":{"line":141,"column":84}},"33":{"start":{"line":142,"column":19},"end":{"line":142,"column":40}},"34":{"start":{"line":144,"column":24},"end":{"line":144,"column":65}},"35":{"start":{"line":145,"column":27},"end":{"line":145,"column":82}},"36":{"start":{"line":147,"column":49},"end":{"line":152,"column":6}},"37":{"start":{"line":154,"column":20},"end":{"line":154,"column":61}},"38":{"start":{"line":155,"column":18},"end":{"line":155,"column":59}},"39":{"start":{"line":157,"column":33},"end":{"line":157,"column":35}},"40":{"start":{"line":158,"column":26},"end":{"line":158,"column":28}},"41":{"start":{"line":160,"column":4},"end":{"line":163,"column":5}},"42":{"start":{"line":161,"column":6},"end":{"line":161,"column":36}},"43":{"start":{"line":162,"column":6},"end":{"line":162,"column":25}},"44":{"start":{"line":164,"column":4},"end":{"line":167,"column":5}},"45":{"start":{"line":165,"column":6},"end":{"line":165,"column":35}},"46":{"start":{"line":166,"column":6},"end":{"line":166,"column":25}},"47":{"start":{"line":168,"column":4},"end":{"line":171,"column":5}},"48":{"start":{"line":169,"column":6},"end":{"line":169,"column":40}},"49":{"start":{"line":170,"column":6},"end":{"line":170,"column":29}},"50":{"start":{"line":173,"column":24},"end":{"line":173,"column":88}},"51":{"start":{"line":175,"column":23},"end":{"line":175,"column":78}},"52":{"start":{"line":176,"column":21},"end":{"line":176,"column":79}},"53":{"start":{"line":177,"column":18},"end":{"line":177,"column":47}},"54":{"start":{"line":179,"column":24},"end":{"line":184,"column":6}},"55":{"start":{"line":185,"column":17},"end":{"line":185,"column":89}},"56":{"start":{"line":187,"column":21},"end":{"line":222,"column":6}},"57":{"start":{"line":188,"column":32},"end":{"line":190,"column":null}},"58":{"start":{"line":192,"column":27},"end":{"line":192,"column":63}},"59":{"start":{"line":193,"column":25},"end":{"line":193,"column":59}},"60":{"start":{"line":195,"column":8},"end":{"line":195,"column":75}},"61":{"start":{"line":196,"column":18},"end":{"line":196,"column":47}},"62":{"start":{"line":197,"column":30},"end":{"line":199,"column":null}},"63":{"start":{"line":202,"column":6},"end":{"line":221,"column":8}},"64":{"start":{"line":224,"column":4},"end":{"line":229,"column":7}},"65":{"start":{"line":232,"column":2},"end":{"line":232,"column":16}}},"fnMap":{"0":{"name":"computeEffectiveYieldBps","decl":{"start":{"line":56,"column":9},"end":{"line":56,"column":33}},"loc":{"start":{"line":56,"column":71},"end":{"line":62,"column":1}}},"1":{"name":"createInvoicesRouter","decl":{"start":{"line":64,"column":16},"end":{"line":64,"column":36}},"loc":{"start":{"line":64,"column":58},"end":{"line":233,"column":1}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":67,"column":30},"end":{"line":67,"column":31}},"loc":{"start":{"line":67,"column":43},"end":{"line":131,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":122,"column":28},"end":{"line":122,"column":29}},"loc":{"start":{"line":122,"column":36},"end":{"line":127,"column":8}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":133,"column":26},"end":{"line":133,"column":27}},"loc":{"start":{"line":133,"column":39},"end":{"line":230,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":187,"column":30},"end":{"line":187,"column":31}},"loc":{"start":{"line":187,"column":42},"end":{"line":222,"column":5}}}},"branchMap":{"0":{"loc":{"start":{"line":59,"column":2},"end":{"line":59,"column":37}},"type":"if","locations":[{"start":{"line":59,"column":2},"end":{"line":59,"column":37}}]},"1":{"loc":{"start":{"line":69,"column":4},"end":{"line":72,"column":5}},"type":"if","locations":[{"start":{"line":69,"column":4},"end":{"line":72,"column":5}}]},"2":{"loc":{"start":{"line":78,"column":4},"end":{"line":81,"column":5}},"type":"if","locations":[{"start":{"line":78,"column":4},"end":{"line":81,"column":5}}]},"3":{"loc":{"start":{"line":92,"column":32},"end":{"line":92,"column":60}},"type":"binary-expr","locations":[{"start":{"line":92,"column":32},"end":{"line":92,"column":53}},{"start":{"line":92,"column":57},"end":{"line":92,"column":60}}]},"4":{"loc":{"start":{"line":93,"column":30},"end":{"line":93,"column":56}},"type":"binary-expr","locations":[{"start":{"line":93,"column":30},"end":{"line":93,"column":49}},{"start":{"line":93,"column":53},"end":{"line":93,"column":56}}]},"5":{"loc":{"start":{"line":95,"column":6},"end":{"line":95,"column":73}},"type":"cond-expr","locations":[{"start":{"line":95,"column":34},"end":{"line":95,"column":37}},{"start":{"line":95,"column":40},"end":{"line":95,"column":73}}]},"6":{"loc":{"start":{"line":126,"column":25},"end":{"line":126,"column":39}},"type":"binary-expr","locations":[{"start":{"line":126,"column":25},"end":{"line":126,"column":31}},{"start":{"line":126,"column":35},"end":{"line":126,"column":39}}]},"7":{"loc":{"start":{"line":140,"column":38},"end":{"line":140,"column":69}},"type":"binary-expr","locations":[{"start":{"line":140,"column":38},"end":{"line":140,"column":62}},{"start":{"line":140,"column":66},"end":{"line":140,"column":69}}]},"8":{"loc":{"start":{"line":141,"column":42},"end":{"line":141,"column":78}},"type":"binary-expr","locations":[{"start":{"line":141,"column":42},"end":{"line":141,"column":70}},{"start":{"line":141,"column":74},"end":{"line":141,"column":78}}]},"9":{"loc":{"start":{"line":144,"column":24},"end":{"line":144,"column":65}},"type":"binary-expr","locations":[{"start":{"line":144,"column":24},"end":{"line":144,"column":50}},{"start":{"line":144,"column":54},"end":{"line":144,"column":65}}]},"10":{"loc":{"start":{"line":145,"column":28},"end":{"line":145,"column":67}},"type":"binary-expr","locations":[{"start":{"line":145,"column":28},"end":{"line":145,"column":57}},{"start":{"line":145,"column":61},"end":{"line":145,"column":67}}]},"11":{"loc":{"start":{"line":154,"column":20},"end":{"line":154,"column":61}},"type":"binary-expr","locations":[{"start":{"line":154,"column":20},"end":{"line":154,"column":45}},{"start":{"line":154,"column":49},"end":{"line":154,"column":61}}]},"12":{"loc":{"start":{"line":155,"column":18},"end":{"line":155,"column":59}},"type":"cond-expr","locations":[{"start":{"line":155,"column":45},"end":{"line":155,"column":50}},{"start":{"line":155,"column":53},"end":{"line":155,"column":59}}]},"13":{"loc":{"start":{"line":160,"column":4},"end":{"line":163,"column":5}},"type":"if","locations":[{"start":{"line":160,"column":4},"end":{"line":163,"column":5}}]},"14":{"loc":{"start":{"line":164,"column":4},"end":{"line":167,"column":5}},"type":"if","locations":[{"start":{"line":164,"column":4},"end":{"line":167,"column":5}}]},"15":{"loc":{"start":{"line":168,"column":4},"end":{"line":171,"column":5}},"type":"if","locations":[{"start":{"line":168,"column":4},"end":{"line":171,"column":5}}]},"16":{"loc":{"start":{"line":173,"column":24},"end":{"line":173,"column":88}},"type":"cond-expr","locations":[{"start":{"line":173,"column":48},"end":{"line":173,"column":83}},{"start":{"line":173,"column":86},"end":{"line":173,"column":88}}]},"17":{"loc":{"start":{"line":177,"column":18},"end":{"line":177,"column":47}},"type":"cond-expr","locations":[{"start":{"line":177,"column":29},"end":{"line":177,"column":43}},{"start":{"line":177,"column":46},"end":{"line":177,"column":47}}]},"18":{"loc":{"start":{"line":192,"column":34},"end":{"line":192,"column":62}},"type":"binary-expr","locations":[{"start":{"line":192,"column":34},"end":{"line":192,"column":55}},{"start":{"line":192,"column":59},"end":{"line":192,"column":62}}]},"19":{"loc":{"start":{"line":193,"column":32},"end":{"line":193,"column":58}},"type":"binary-expr","locations":[{"start":{"line":193,"column":32},"end":{"line":193,"column":51}},{"start":{"line":193,"column":55},"end":{"line":193,"column":58}}]},"20":{"loc":{"start":{"line":195,"column":8},"end":{"line":195,"column":75}},"type":"cond-expr","locations":[{"start":{"line":195,"column":36},"end":{"line":195,"column":39}},{"start":{"line":195,"column":42},"end":{"line":195,"column":75}}]}},"s":{"0":12,"1":12,"2":12,"3":0,"4":12,"5":12,"6":42,"7":42,"8":10,"9":10,"10":1,"11":1,"12":9,"13":9,"14":1,"15":1,"16":8,"17":8,"18":8,"19":8,"20":8,"21":8,"22":8,"23":8,"24":4,"25":8,"26":42,"27":3,"28":3,"29":3,"30":3,"31":3,"32":3,"33":3,"34":3,"35":3,"36":3,"37":3,"38":3,"39":3,"40":3,"41":3,"42":1,"43":1,"44":3,"45":1,"46":1,"47":3,"48":1,"49":1,"50":3,"51":3,"52":3,"53":3,"54":3,"55":3,"56":3,"57":4,"58":4,"59":4,"60":4,"61":4,"62":4,"63":4,"64":3,"65":42},"f":{"0":12,"1":42,"2":10,"3":4,"4":3,"5":4},"b":{"0":[0],"1":[1],"2":[1],"3":[8,0],"4":[8,0],"5":[0,8],"6":[4,0],"7":[3,2],"8":[3,2],"9":[3,2],"10":[3,2],"11":[3,0],"12":[1,2],"13":[1],"14":[1],"15":[1],"16":[1,2],"17":[3,0],"18":[4,0],"19":[4,0],"20":[0,4]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/leaderboard.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/leaderboard.ts","statementMap":{"0":{"start":{"line":6,"column":17},"end":{"line":6,"column":25}},"1":{"start":{"line":8,"column":2},"end":{"line":24,"column":5}},"2":{"start":{"line":9,"column":23},"end":{"line":9,"column":38}},"3":{"start":{"line":10,"column":18},"end":{"line":10,"column":55}},"4":{"start":{"line":12,"column":16},"end":{"line":12,"column":18}},"5":{"start":{"line":13,"column":4},"end":{"line":20,"column":5}},"6":{"start":{"line":14,"column":21},"end":{"line":14,"column":55}},"7":{"start":{"line":15,"column":6},"end":{"line":18,"column":7}},"8":{"start":{"line":16,"column":8},"end":{"line":16,"column":67}},"9":{"start":{"line":17,"column":8},"end":{"line":17,"column":15}},"10":{"start":{"line":19,"column":6},"end":{"line":19,"column":36}},"11":{"start":{"line":22,"column":40},"end":{"line":22,"column":72}},"12":{"start":{"line":23,"column":4},"end":{"line":23,"column":22}},"13":{"start":{"line":26,"column":2},"end":{"line":26,"column":16}}},"fnMap":{"0":{"name":"createLeaderboardRouter","decl":{"start":{"line":5,"column":16},"end":{"line":5,"column":39}},"loc":{"start":{"line":5,"column":61},"end":{"line":27,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":8,"column":29},"end":{"line":8,"column":30}},"loc":{"start":{"line":8,"column":42},"end":{"line":24,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":13,"column":4},"end":{"line":20,"column":5}},"type":"if","locations":[{"start":{"line":13,"column":4},"end":{"line":20,"column":5}}]},"1":{"loc":{"start":{"line":15,"column":6},"end":{"line":18,"column":7}},"type":"if","locations":[{"start":{"line":15,"column":6},"end":{"line":18,"column":7}}]},"2":{"loc":{"start":{"line":15,"column":10},"end":{"line":15,"column":37}},"type":"binary-expr","locations":[{"start":{"line":15,"column":10},"end":{"line":15,"column":23}},{"start":{"line":15,"column":27},"end":{"line":15,"column":37}}]}},"s":{"0":42,"1":42,"2":8,"3":8,"4":8,"5":8,"6":3,"7":3,"8":1,"9":1,"10":2,"11":7,"12":7,"13":42},"f":{"0":42,"1":8},"b":{"0":[3],"1":[1],"2":[3,2]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/reputation.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/reputation.ts","statementMap":{"0":{"start":{"line":31,"column":17},"end":{"line":31,"column":25}},"1":{"start":{"line":33,"column":2},"end":{"line":106,"column":5}},"2":{"start":{"line":34,"column":24},"end":{"line":34,"column":34}},"3":{"start":{"line":35,"column":27},"end":{"line":35,"column":70}},"4":{"start":{"line":37,"column":22},"end":{"line":47,"column":54}},"5":{"start":{"line":49,"column":4},"end":{"line":59,"column":5}},"6":{"start":{"line":50,"column":6},"end":{"line":57,"column":9}},"7":{"start":{"line":58,"column":6},"end":{"line":58,"column":13}},"8":{"start":{"line":61,"column":21},"end":{"line":61,"column":23}},"9":{"start":{"line":62,"column":4},"end":{"line":66,"column":5}},"10":{"start":{"line":63,"column":6},"end":{"line":63,"column":40}},"11":{"start":{"line":64,"column":11},"end":{"line":66,"column":5}},"12":{"start":{"line":65,"column":6},"end":{"line":65,"column":40}},"13":{"start":{"line":68,"column":45},"end":{"line":68,"column":54}},"14":{"start":{"line":69,"column":4},"end":{"line":73,"column":5}},"15":{"start":{"line":70,"column":6},"end":{"line":70,"column":76}},"16":{"start":{"line":71,"column":11},"end":{"line":73,"column":5}},"17":{"start":{"line":72,"column":6},"end":{"line":72,"column":76}},"18":{"start":{"line":75,"column":24},"end":{"line":84,"column":null}},"19":{"start":{"line":91,"column":41},"end":{"line":103,"column":6}},"20":{"start":{"line":97,"column":41},"end":{"line":102,"column":8}},"21":{"start":{"line":105,"column":4},"end":{"line":105,"column":23}},"22":{"start":{"line":108,"column":2},"end":{"line":108,"column":16}}},"fnMap":{"0":{"name":"createReputationRouter","decl":{"start":{"line":30,"column":16},"end":{"line":30,"column":38}},"loc":{"start":{"line":30,"column":60},"end":{"line":109,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":33,"column":37},"end":{"line":33,"column":38}},"loc":{"start":{"line":33,"column":50},"end":{"line":106,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":97,"column":31},"end":{"line":97,"column":32}},"loc":{"start":{"line":97,"column":41},"end":{"line":102,"column":8}}}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":27},"end":{"line":35,"column":70}},"type":"binary-expr","locations":[{"start":{"line":35,"column":27},"end":{"line":35,"column":61}},{"start":{"line":35,"column":65},"end":{"line":35,"column":70}}]},"1":{"loc":{"start":{"line":49,"column":4},"end":{"line":59,"column":5}},"type":"if","locations":[{"start":{"line":49,"column":4},"end":{"line":59,"column":5}}]},"2":{"loc":{"start":{"line":62,"column":4},"end":{"line":66,"column":5}},"type":"if","locations":[{"start":{"line":62,"column":4},"end":{"line":66,"column":5}},{"start":{"line":64,"column":11},"end":{"line":66,"column":5}}]},"3":{"loc":{"start":{"line":64,"column":11},"end":{"line":66,"column":5}},"type":"if","locations":[{"start":{"line":64,"column":11},"end":{"line":66,"column":5}}]},"4":{"loc":{"start":{"line":69,"column":4},"end":{"line":73,"column":5}},"type":"if","locations":[{"start":{"line":69,"column":4},"end":{"line":73,"column":5}},{"start":{"line":71,"column":11},"end":{"line":73,"column":5}}]},"5":{"loc":{"start":{"line":71,"column":11},"end":{"line":73,"column":5}},"type":"if","locations":[{"start":{"line":71,"column":11},"end":{"line":73,"column":5}}]}},"s":{"0":42,"1":42,"2":9,"3":9,"4":9,"5":9,"6":1,"7":1,"8":8,"9":8,"10":1,"11":7,"12":1,"13":8,"14":8,"15":1,"16":7,"17":1,"18":8,"19":8,"20":13,"21":8,"22":42},"f":{"0":42,"1":9,"2":13},"b":{"0":[9,6],"1":[1],"2":[1,7],"3":[1],"4":[1,7],"5":[1]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/stats.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/api/routes/stats.ts","statementMap":{"0":{"start":{"line":11,"column":17},"end":{"line":11,"column":25}},"1":{"start":{"line":13,"column":2},"end":{"line":16,"column":5}},"2":{"start":{"line":14,"column":33},"end":{"line":14,"column":53}},"3":{"start":{"line":15,"column":4},"end":{"line":15,"column":20}},"4":{"start":{"line":18,"column":2},"end":{"line":26,"column":5}},"5":{"start":{"line":19,"column":20},"end":{"line":19,"column":56}},"6":{"start":{"line":20,"column":4},"end":{"line":23,"column":5}},"7":{"start":{"line":21,"column":6},"end":{"line":21,"column":78}},"8":{"start":{"line":22,"column":6},"end":{"line":22,"column":13}},"9":{"start":{"line":24,"column":41},"end":{"line":24,"column":93}},"10":{"start":{"line":25,"column":4},"end":{"line":25,"column":22}},"11":{"start":{"line":28,"column":2},"end":{"line":28,"column":16}}},"fnMap":{"0":{"name":"createStatsRouter","decl":{"start":{"line":10,"column":16},"end":{"line":10,"column":33}},"loc":{"start":{"line":10,"column":55},"end":{"line":29,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":23},"end":{"line":13,"column":24}},"loc":{"start":{"line":13,"column":37},"end":{"line":16,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":18,"column":31},"end":{"line":18,"column":32}},"loc":{"start":{"line":18,"column":44},"end":{"line":26,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":19,"column":20},"end":{"line":19,"column":56}},"type":"binary-expr","locations":[{"start":{"line":19,"column":20},"end":{"line":19,"column":47}},{"start":{"line":19,"column":51},"end":{"line":19,"column":56}}]},"1":{"loc":{"start":{"line":20,"column":4},"end":{"line":23,"column":5}},"type":"if","locations":[{"start":{"line":20,"column":4},"end":{"line":23,"column":5}}]}},"s":{"0":42,"1":42,"2":7,"3":7,"4":42,"5":3,"6":3,"7":1,"8":1,"9":2,"10":2,"11":42},"f":{"0":42,"1":7,"2":3},"b":{"0":[3,0],"1":[1]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/database/db.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/database/db.ts","statementMap":{"0":{"start":{"line":4,"column":35},"end":{"line":4,"column":39}},"1":{"start":{"line":7,"column":2},"end":{"line":12,"column":3}},"2":{"start":{"line":8,"column":4},"end":{"line":8,"column":44}},"3":{"start":{"line":9,"column":4},"end":{"line":9,"column":36}},"4":{"start":{"line":10,"column":4},"end":{"line":10,"column":35}},"5":{"start":{"line":11,"column":4},"end":{"line":11,"column":25}},"6":{"start":{"line":13,"column":2},"end":{"line":13,"column":12}},"7":{"start":{"line":17,"column":2},"end":{"line":20,"column":3}},"8":{"start":{"line":18,"column":4},"end":{"line":18,"column":15}},"9":{"start":{"line":19,"column":4},"end":{"line":19,"column":14}},"10":{"start":{"line":24,"column":2},"end":{"line":24,"column":12}}},"fnMap":{"0":{"name":"getDb","decl":{"start":{"line":6,"column":16},"end":{"line":6,"column":21}},"loc":{"start":{"line":6,"column":37},"end":{"line":14,"column":1}}},"1":{"name":"closeDb","decl":{"start":{"line":16,"column":16},"end":{"line":16,"column":23}},"loc":{"start":{"line":16,"column":23},"end":{"line":21,"column":1}}},"2":{"name":"resetDb","decl":{"start":{"line":23,"column":16},"end":{"line":23,"column":23}},"loc":{"start":{"line":23,"column":23},"end":{"line":25,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":7,"column":2},"end":{"line":12,"column":3}},"type":"if","locations":[{"start":{"line":7,"column":2},"end":{"line":12,"column":3}}]},"1":{"loc":{"start":{"line":8,"column":22},"end":{"line":8,"column":42}},"type":"binary-expr","locations":[{"start":{"line":8,"column":22},"end":{"line":8,"column":28}},{"start":{"line":8,"column":32},"end":{"line":8,"column":42}}]},"2":{"loc":{"start":{"line":17,"column":2},"end":{"line":20,"column":3}},"type":"if","locations":[{"start":{"line":17,"column":2},"end":{"line":20,"column":3}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"f":{"0":0,"1":0,"2":0},"b":{"0":[0],"1":[0,0],"2":[0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/database/schema.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/database/schema.ts","statementMap":{"0":{"start":{"line":4,"column":2},"end":{"line":79,"column":5}}},"fnMap":{"0":{"name":"initializeSchema","decl":{"start":{"line":3,"column":16},"end":{"line":3,"column":32}},"loc":{"start":{"line":3,"column":54},"end":{"line":80,"column":1}}}},"branchMap":{},"s":{"0":42},"f":{"0":42},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/services/leaderboardService.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/services/leaderboardService.ts","statementMap":{"0":{"start":{"line":24,"column":20},"end":{"line":24,"column":53}},"1":{"start":{"line":28,"column":2},"end":{"line":67,"column":3}},"2":{"start":{"line":29,"column":4},"end":{"line":48,"column":48}},"3":{"start":{"line":50,"column":4},"end":{"line":66,"column":41}},"4":{"start":{"line":69,"column":21},"end":{"line":74,"column":null}},"5":{"start":{"line":77,"column":2},"end":{"line":87,"column":5}},"6":{"start":{"line":78,"column":22},"end":{"line":78,"column":80}},"7":{"start":{"line":79,"column":4},"end":{"line":86,"column":6}}},"fnMap":{"0":{"name":"getLeaderboard","decl":{"start":{"line":19,"column":16},"end":{"line":19,"column":30}},"loc":{"start":{"line":22,"column":16},"end":{"line":88,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":77,"column":18},"end":{"line":77,"column":19}},"loc":{"start":{"line":77,"column":31},"end":{"line":87,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":21,"column":2},"end":{"line":21,"column":20}},"type":"default-arg","locations":[{"start":{"line":21,"column":18},"end":{"line":21,"column":20}}]},"1":{"loc":{"start":{"line":28,"column":2},"end":{"line":67,"column":3}},"type":"if","locations":[{"start":{"line":28,"column":2},"end":{"line":67,"column":3}},{"start":{"line":49,"column":9},"end":{"line":67,"column":3}}]},"2":{"loc":{"start":{"line":85,"column":26},"end":{"line":85,"column":45}},"type":"binary-expr","locations":[{"start":{"line":85,"column":26},"end":{"line":85,"column":40}},{"start":{"line":85,"column":44},"end":{"line":85,"column":45}}]}},"s":{"0":7,"1":7,"2":0,"3":7,"4":7,"5":7,"6":16,"7":16},"f":{"0":7,"1":16},"b":{"0":[0],"1":[0,7],"2":[16,16]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/services/statsService.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/indexer/src/services/statsService.ts","statementMap":{"0":{"start":{"line":30,"column":38},"end":{"line":30,"column":42}},"1":{"start":{"line":36,"column":14},"end":{"line":36,"column":24}},"2":{"start":{"line":38,"column":2},"end":{"line":40,"column":3}},"3":{"start":{"line":39,"column":4},"end":{"line":39,"column":29}},"4":{"start":{"line":42,"column":17},"end":{"line":56,"column":null}},"5":{"start":{"line":66,"column":23},"end":{"line":75,"column":54}},"6":{"start":{"line":77,"column":48},"end":{"line":77,"column":50}},"7":{"start":{"line":78,"column":2},"end":{"line":80,"column":3}},"8":{"start":{"line":79,"column":4},"end":{"line":79,"column":50}},"9":{"start":{"line":82,"column":22},"end":{"line":82,"column":75}},"10":{"start":{"line":84,"column":31},"end":{"line":95,"column":4}},"11":{"start":{"line":97,"column":2},"end":{"line":97,"column":41}},"12":{"start":{"line":98,"column":2},"end":{"line":98,"column":15}},"13":{"start":{"line":105,"column":19},"end":{"line":105,"column":21}},"14":{"start":{"line":106,"column":2},"end":{"line":110,"column":3}},"15":{"start":{"line":107,"column":4},"end":{"line":107,"column":57}},"16":{"start":{"line":108,"column":9},"end":{"line":110,"column":3}},"17":{"start":{"line":109,"column":4},"end":{"line":109,"column":57}},"18":{"start":{"line":112,"column":15},"end":{"line":127,"column":33}},"19":{"start":{"line":129,"column":2},"end":{"line":129,"column":14}},"20":{"start":{"line":133,"column":2},"end":{"line":133,"column":21}},"21":{"start":{"line":134,"column":2},"end":{"line":134,"column":30}},"22":{"start":{"line":138,"column":2},"end":{"line":138,"column":21}}},"fnMap":{"0":{"name":"getProtocolStats","decl":{"start":{"line":32,"column":16},"end":{"line":32,"column":32}},"loc":{"start":{"line":34,"column":28},"end":{"line":99,"column":1}}},"1":{"name":"getStatsHistory","decl":{"start":{"line":101,"column":16},"end":{"line":101,"column":31}},"loc":{"start":{"line":103,"column":39},"end":{"line":130,"column":1}}},"2":{"name":"refreshStats","decl":{"start":{"line":132,"column":16},"end":{"line":132,"column":28}},"loc":{"start":{"line":132,"column":50},"end":{"line":135,"column":1}}},"3":{"name":"clearStatsCache","decl":{"start":{"line":137,"column":16},"end":{"line":137,"column":31}},"loc":{"start":{"line":137,"column":31},"end":{"line":139,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":34,"column":2},"end":{"line":34,"column":28}},"type":"default-arg","locations":[{"start":{"line":34,"column":23},"end":{"line":34,"column":28}}]},"1":{"loc":{"start":{"line":38,"column":2},"end":{"line":40,"column":3}},"type":"if","locations":[{"start":{"line":38,"column":2},"end":{"line":40,"column":3}}]},"2":{"loc":{"start":{"line":38,"column":6},"end":{"line":38,"column":60}},"type":"binary-expr","locations":[{"start":{"line":38,"column":6},"end":{"line":38,"column":17}},{"start":{"line":38,"column":21},"end":{"line":38,"column":60}}]},"3":{"loc":{"start":{"line":82,"column":22},"end":{"line":82,"column":75}},"type":"cond-expr","locations":[{"start":{"line":82,"column":41},"end":{"line":82,"column":71}},{"start":{"line":82,"column":74},"end":{"line":82,"column":75}}]},"4":{"loc":{"start":{"line":85,"column":19},"end":{"line":85,"column":36}},"type":"binary-expr","locations":[{"start":{"line":85,"column":19},"end":{"line":85,"column":31}},{"start":{"line":85,"column":35},"end":{"line":85,"column":36}}]},"5":{"loc":{"start":{"line":86,"column":17},"end":{"line":86,"column":35}},"type":"binary-expr","locations":[{"start":{"line":86,"column":17},"end":{"line":86,"column":30}},{"start":{"line":86,"column":34},"end":{"line":86,"column":35}}]},"6":{"loc":{"start":{"line":87,"column":15},"end":{"line":87,"column":31}},"type":"binary-expr","locations":[{"start":{"line":87,"column":15},"end":{"line":87,"column":26}},{"start":{"line":87,"column":30},"end":{"line":87,"column":31}}]},"7":{"loc":{"start":{"line":88,"column":20},"end":{"line":88,"column":41}},"type":"binary-expr","locations":[{"start":{"line":88,"column":20},"end":{"line":88,"column":36}},{"start":{"line":88,"column":40},"end":{"line":88,"column":41}}]},"8":{"loc":{"start":{"line":89,"column":18},"end":{"line":89,"column":37}},"type":"binary-expr","locations":[{"start":{"line":89,"column":18},"end":{"line":89,"column":32}},{"start":{"line":89,"column":36},"end":{"line":89,"column":37}}]},"9":{"loc":{"start":{"line":90,"column":19},"end":{"line":90,"column":39}},"type":"binary-expr","locations":[{"start":{"line":90,"column":19},"end":{"line":90,"column":34}},{"start":{"line":90,"column":38},"end":{"line":90,"column":39}}]},"10":{"loc":{"start":{"line":92,"column":35},"end":{"line":92,"column":59}},"type":"binary-expr","locations":[{"start":{"line":92,"column":35},"end":{"line":92,"column":54}},{"start":{"line":92,"column":58},"end":{"line":92,"column":59}}]},"11":{"loc":{"start":{"line":103,"column":2},"end":{"line":103,"column":39}},"type":"default-arg","locations":[{"start":{"line":103,"column":34},"end":{"line":103,"column":39}}]},"12":{"loc":{"start":{"line":106,"column":2},"end":{"line":110,"column":3}},"type":"if","locations":[{"start":{"line":106,"column":2},"end":{"line":110,"column":3}},{"start":{"line":108,"column":9},"end":{"line":110,"column":3}}]},"13":{"loc":{"start":{"line":108,"column":9},"end":{"line":110,"column":3}},"type":"if","locations":[{"start":{"line":108,"column":9},"end":{"line":110,"column":3}}]}},"s":{"0":5,"1":7,"2":7,"3":1,"4":6,"5":6,"6":6,"7":6,"8":6,"9":6,"10":6,"11":6,"12":6,"13":2,"14":2,"15":1,"16":1,"17":0,"18":2,"19":2,"20":0,"21":0,"22":9},"f":{"0":7,"1":2,"2":0,"3":9},"b":{"0":[7],"1":[1],"2":[7,1],"3":[4,2],"4":[6,2],"5":[6,2],"6":[6,2],"7":[6,5],"8":[6,5],"9":[6,4],"10":[6,2],"11":[0],"12":[1,1],"13":[0]}} +} diff --git a/indexer/coverage/lcov-report/base.css b/indexer/coverage/lcov-report/base.css new file mode 100644 index 00000000..f418035b --- /dev/null +++ b/indexer/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/indexer/coverage/lcov-report/block-navigation.js b/indexer/coverage/lcov-report/block-navigation.js new file mode 100644 index 00000000..530d1ed2 --- /dev/null +++ b/indexer/coverage/lcov-report/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selector that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/indexer/coverage/lcov-report/favicon.png b/indexer/coverage/lcov-report/favicon.png new file mode 100644 index 00000000..c1525b81 Binary files /dev/null and b/indexer/coverage/lcov-report/favicon.png differ diff --git a/indexer/coverage/lcov-report/index.html b/indexer/coverage/lcov-report/index.html new file mode 100644 index 00000000..3d04df68 --- /dev/null +++ b/indexer/coverage/lcov-report/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 90.86% + Statements + 179/197 +
+ + +
+ 72.81% + Branches + 75/103 +
+ + +
+ 83.33% + Functions + 25/30 +
+ + +
+ 91.23% + Lines + 177/194 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
81.81%9/110%0/650%1/281.81%9/11
src/api/routes +
+
99.3%142/14378.12%50/64100%18/18100%140/140
src/database +
+
8.33%1/120%0/425%1/48.33%1/12
src/services +
+
87.09%27/3186.2%25/2983.33%5/687.09%27/31
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/prettify.css b/indexer/coverage/lcov-report/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/indexer/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/indexer/coverage/lcov-report/prettify.js b/indexer/coverage/lcov-report/prettify.js new file mode 100644 index 00000000..b3225238 --- /dev/null +++ b/indexer/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/indexer/coverage/lcov-report/sort-arrow-sprite.png b/indexer/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 00000000..6ed68316 Binary files /dev/null and b/indexer/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/indexer/coverage/lcov-report/sorter.js b/indexer/coverage/lcov-report/sorter.js new file mode 100644 index 00000000..4ed70ae5 --- /dev/null +++ b/indexer/coverage/lcov-report/sorter.js @@ -0,0 +1,210 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + + // Try to create a RegExp from the searchValue. If it fails (invalid regex), + // it will be treated as a plain text search + let searchRegex; + try { + searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive + } catch (error) { + searchRegex = null; + } + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + let isMatch = false; + + if (searchRegex) { + // If a valid regex was created, use it for matching + isMatch = searchRegex.test(row.textContent); + } else { + // Otherwise, fall back to the original plain text search + isMatch = row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()); + } + + row.style.display = isMatch ? '' : 'none'; + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/indexer/coverage/lcov-report/src/api/routes/events.ts.html b/indexer/coverage/lcov-report/src/api/routes/events.ts.html new file mode 100644 index 00000000..af768f83 --- /dev/null +++ b/indexer/coverage/lcov-report/src/api/routes/events.ts.html @@ -0,0 +1,331 @@ + + + + + + Code coverage report for src/api/routes/events.ts + + + + + + + + + +
+
+

All files / src/api/routes events.ts

+
+ +
+ 100% + Statements + 28/28 +
+ + +
+ 75% + Branches + 9/12 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 26/26 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +42x +  +42x +5x +5x +5x +5x +5x +  +5x +1x +1x +  +  +4x +4x +  +4x +1x +1x +1x +1x +  +  +4x +  +  +4x +  +  +  +  +  +4x +4x +  +  +4x +  +  +  +  +  +  +  +4x +  +6x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +42x +  + 
import { Router } from 'express';
+import type Database from 'better-sqlite3';
+ 
+interface EventRow {
+  id: number;
+  invoice_id: number;
+  event_type: string;
+  ledger: number;
+  timestamp: number;
+  data: string;
+  freelancer: string;
+  payer: string;
+  funder: string | null;
+}
+ 
+export function createEventsRouter(db: Database.Database): Router {
+  const router = Router();
+ 
+  router.get('/events', (req, res) => {
+    const address = req.query.address as string;
+    const typesStr = req.query.types as string | undefined;
+    const page = Math.max(1, parseInt(req.query.page as string || '1', 10));
+    const pageSize = Math.max(1, parseInt(req.query.pageSize as string || '20', 10));
+    const offset = (page - 1) * pageSize;
+ 
+    if (!address) {
+      res.status(400).json({ error: 'Address parameter is required' });
+      return;
+    }
+ 
+    const conditions: string[] = ['(i.freelancer = ? OR i.payer = ? OR i.funder = ?)'];
+    const params: any[] = [address, address, address];
+ 
+    if (typesStr) {
+      const types = typesStr.split(',');
+      const placeHolders = types.map(() => '?').join(',');
+      conditions.push(`e.event_type IN (${placeHolders})`);
+      params.push(...types);
+    }
+ 
+    const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
+ 
+    // Count query
+    const countQuery = `
+      SELECT COUNT(*) as total
+      FROM events e
+      JOIN invoices i ON e.invoice_id = i.id
+      ${whereClause}
+    `;
+    const totalRow = db.prepare(countQuery).get(...params) as { total: number };
+    const total = totalRow ? totalRow.total : 0;
+ 
+    // Select query
+    const selectQuery = `
+      SELECT e.*, i.freelancer, i.payer, i.funder
+      FROM events e
+      JOIN invoices i ON e.invoice_id = i.id
+      ${whereClause}
+      ORDER BY e.timestamp DESC, e.id DESC
+      LIMIT ? OFFSET ?
+    `;
+    const rows = db.prepare(selectQuery).all(...params, pageSize, offset) as EventRow[];
+ 
+    const events = rows.map(r => ({
+      id: r.id,
+      invoiceId: r.invoice_id,
+      type: r.event_type,
+      ledger: r.ledger,
+      timestamp: r.timestamp,
+      data: JSON.parse(r.data || '{}'),
+    }));
+ 
+    res.json({
+      events,
+      total,
+      page,
+      pageSize
+    });
+  });
+ 
+  return router;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/api/routes/index.html b/indexer/coverage/lcov-report/src/api/routes/index.html new file mode 100644 index 00000000..c0789c10 --- /dev/null +++ b/indexer/coverage/lcov-report/src/api/routes/index.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for src/api/routes + + + + + + + + + +
+
+

All files src/api/routes

+
+ +
+ 99.3% + Statements + 142/143 +
+ + +
+ 78.12% + Branches + 50/64 +
+ + +
+ 100% + Functions + 18/18 +
+ + +
+ 100% + Lines + 140/140 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
events.ts +
+
100%28/2875%9/12100%4/4100%26/26
invoices.ts +
+
98.48%65/6672.22%26/36100%6/6100%65/65
leaderboard.ts +
+
100%14/14100%4/4100%2/2100%14/14
reputation.ts +
+
100%23/23100%9/9100%3/3100%23/23
stats.ts +
+
100%12/1266.66%2/3100%3/3100%12/12
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/api/routes/invoices.ts.html b/indexer/coverage/lcov-report/src/api/routes/invoices.ts.html new file mode 100644 index 00000000..f1531c25 --- /dev/null +++ b/indexer/coverage/lcov-report/src/api/routes/invoices.ts.html @@ -0,0 +1,784 @@ + + + + + + Code coverage report for src/api/routes/invoices.ts + + + + + + + + + +
+
+

All files / src/api/routes invoices.ts

+
+ +
+ 98.48% + Statements + 65/66 +
+ + +
+ 72.22% + Branches + 26/36 +
+ + +
+ 100% + Functions + 6/6 +
+ + +
+ 100% + Lines + 65/65 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +12x +12x +12x +12x +12x +  +  +  +42x +  +42x +10x +10x +1x +1x +  +  +9x +  +  +  +9x +1x +1x +  +  +8x +  +  +  +8x +  +  +  +  +8x +8x +  +8x +  +8x +8x +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +8x +  +  +42x +3x +  +3x +3x +3x +  +3x +3x +3x +  +3x +3x +  +3x +  +  +  +  +  +  +3x +3x +  +3x +3x +  +3x +1x +1x +  +3x +1x +1x +  +3x +1x +1x +  +  +3x +  +3x +3x +3x +  +3x +  +  +  +  +  +3x +  +3x +4x +  +  +  +4x +4x +  +4x +4x +4x +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +42x +  + 
import { Router } from 'express';
+import type Database from 'better-sqlite3';
+ 
+interface InvoiceRow {
+  id: number;
+  freelancer: string;
+  payer: string;
+  token: string;
+  amount: string;
+  due_date: number;
+  discount_rate: number;
+  status: string;
+  funder: string | null;
+  funded_at: number | null;
+  amount_funded: string;
+  amount_paid: string;
+  referral_code: string | null;
+  submitter_reputation: number;
+  created_at: number;
+}
+ 
+interface EventRow {
+  event_type: string;
+  ledger: number;
+  timestamp: number;
+  data: string;
+}
+ 
+interface InvoiceResponse {
+  id: number;
+  freelancer: string;
+  payer: string;
+  token: string;
+  amount: string;
+  dueDate: number;
+  discountRate: number;
+  status: string;
+  funder: string | null;
+  fundedAt: number | null;
+  amountFunded: string;
+  amountPaid: string;
+  referralCode: string | null;
+  submitterReputation: number;
+  createdAt: number;
+  effectiveYieldBps: number;
+  remainingBalance: string;
+  daysUntilExpiry: number;
+  events: Array<{
+    type: string;
+    ledger: number;
+    timestamp: number;
+    data: Record<string, unknown>;
+  }>;
+}
+ 
+function computeEffectiveYieldBps(discountRate: number, dueDate: number): number {
+  const now = Math.floor(Date.now() / 1000);
+  const secondsToExpiry = dueDate - now;
+  Iif (secondsToExpiry <= 0) return 0;
+  const daysToExpiry = secondsToExpiry / (24 * 60 * 60);
+  return Math.round((discountRate * daysToExpiry) / 365);
+}
+ 
+export function createInvoicesRouter(db: Database.Database): Router {
+  const router = Router();
+ 
+  router.get('/invoices/:id', (req, res) => {
+    const invoiceId = parseInt(req.params.id, 10);
+    if (isNaN(invoiceId)) {
+      res.status(400).json({ error: 'Invalid invoice ID' });
+      return;
+    }
+ 
+    const invoice = db
+      .prepare('SELECT * FROM invoices WHERE id = ?')
+      .get(invoiceId) as InvoiceRow | undefined;
+ 
+    if (!invoice) {
+      res.status(404).json({ error: 'Invoice not found' });
+      return;
+    }
+ 
+    const eventRows = db
+      .prepare('SELECT * FROM events WHERE invoice_id = ? ORDER BY timestamp ASC')
+      .all(invoiceId) as EventRow[];
+ 
+    const effectiveYieldBps = computeEffectiveYieldBps(
+      invoice.discount_rate,
+      invoice.due_date
+    );
+ 
+    const amountFunded = BigInt(invoice.amount_funded || '0');
+    const amountPaid = BigInt(invoice.amount_paid || '0');
+    const remainingBalance =
+      amountPaid > amountFunded ? '0' : String(amountFunded - amountPaid);
+ 
+    const now = Math.floor(Date.now() / 1000);
+    const daysUntilExpiry = Math.max(
+      0,
+      Math.ceil((invoice.due_date - now) / (24 * 60 * 60))
+    );
+ 
+    const response: InvoiceResponse = {
+      id: invoice.id,
+      freelancer: invoice.freelancer,
+      payer: invoice.payer,
+      token: invoice.token,
+      amount: invoice.amount,
+      dueDate: invoice.due_date,
+      discountRate: invoice.discount_rate,
+      status: invoice.status,
+      funder: invoice.funder,
+      fundedAt: invoice.funded_at,
+      amountFunded: invoice.amount_funded,
+      amountPaid: invoice.amount_paid,
+      referralCode: invoice.referral_code,
+      submitterReputation: invoice.submitter_reputation,
+      createdAt: invoice.created_at,
+      effectiveYieldBps,
+      remainingBalance,
+      daysUntilExpiry,
+      events: eventRows.map((e) => ({
+        type: e.event_type,
+        ledger: e.ledger,
+        timestamp: e.timestamp,
+        data: JSON.parse(e.data || '{}'),
+      })),
+    };
+ 
+    res.json(response);
+  });
+ 
+  router.get('/invoices', (req, res) => {
+    res.setHeader('Cache-Control', 'max-age=10');
+ 
+    const state = req.query.state as string | undefined;
+    const token = req.query.token as string | undefined;
+    const submitter = req.query.submitter as string | undefined;
+ 
+    const page = Math.max(1, parseInt(req.query.page as string || '1', 10));
+    const pageSize = Math.max(1, parseInt(req.query.pageSize as string || '20', 10));
+    const offset = (page - 1) * pageSize;
+ 
+    const sortByParam = req.query.sortBy as string || 'createdAt';
+    const sortOrderParam = (req.query.sortOrder as string || 'desc').toLowerCase();
+ 
+    const sortFieldMap: Record<string, string> = {
+      createdAt: 'created_at',
+      dueDate: 'due_date',
+      amount: 'CAST(amount AS REAL)',
+      discountRate: 'discount_rate'
+    };
+ 
+    const orderBy = sortFieldMap[sortByParam] || 'created_at';
+    const order = sortOrderParam === 'asc' ? 'ASC' : 'DESC';
+ 
+    const conditions: string[] = [];
+    const params: any[] = [];
+ 
+    if (state) {
+      conditions.push('status = ?');
+      params.push(state);
+    }
+    if (token) {
+      conditions.push('token = ?');
+      params.push(token);
+    }
+    if (submitter) {
+      conditions.push('freelancer = ?');
+      params.push(submitter);
+    }
+ 
+    const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
+ 
+    const countQuery = `SELECT COUNT(*) as total FROM invoices ${whereClause}`;
+    const totalRow = db.prepare(countQuery).get(...params) as { total: number };
+    const total = totalRow ? totalRow.total : 0;
+ 
+    const selectQuery = `
+      SELECT * FROM invoices
+      ${whereClause}
+      ORDER BY ${orderBy} ${order}
+      LIMIT ? OFFSET ?
+    `;
+    const rows = db.prepare(selectQuery).all(...params, pageSize, offset) as InvoiceRow[];
+ 
+    const invoices = rows.map((invoice) => {
+      const effectiveYieldBps = computeEffectiveYieldBps(
+        invoice.discount_rate,
+        invoice.due_date
+      );
+      const amountFunded = BigInt(invoice.amount_funded || '0');
+      const amountPaid = BigInt(invoice.amount_paid || '0');
+      const remainingBalance =
+        amountPaid > amountFunded ? '0' : String(amountFunded - amountPaid);
+      const now = Math.floor(Date.now() / 1000);
+      const daysUntilExpiry = Math.max(
+        0,
+        Math.ceil((invoice.due_date - now) / (24 * 60 * 60))
+      );
+ 
+      return {
+        id: invoice.id,
+        freelancer: invoice.freelancer,
+        payer: invoice.payer,
+        token: invoice.token,
+        amount: invoice.amount,
+        dueDate: invoice.due_date,
+        discountRate: invoice.discount_rate,
+        status: invoice.status,
+        funder: invoice.funder,
+        fundedAt: invoice.funded_at,
+        amountFunded: invoice.amount_funded,
+        amountPaid: invoice.amount_paid,
+        referralCode: invoice.referral_code,
+        submitterReputation: invoice.submitter_reputation,
+        createdAt: invoice.created_at,
+        effectiveYieldBps,
+        remainingBalance,
+        daysUntilExpiry,
+      };
+    });
+ 
+    res.json({
+      invoices,
+      total,
+      page,
+      pageSize
+    });
+  });
+ 
+  return router;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/api/routes/leaderboard.ts.html b/indexer/coverage/lcov-report/src/api/routes/leaderboard.ts.html new file mode 100644 index 00000000..a6193e52 --- /dev/null +++ b/indexer/coverage/lcov-report/src/api/routes/leaderboard.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/api/routes/leaderboard.ts + + + + + + + + + +
+
+

All files / src/api/routes leaderboard.ts

+
+ +
+ 100% + Statements + 14/14 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 14/14 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28  +  +  +  +  +42x +  +42x +8x +8x +  +8x +8x +3x +3x +1x +1x +  +2x +  +  +7x +7x +  +  +42x +  + 
import { Router } from 'express';
+import type Database from 'better-sqlite3';
+import { getLeaderboard, type LeaderboardEntry } from '../../services/leaderboardService.js';
+ 
+export function createLeaderboardRouter(db: Database.Database): Router {
+  const router = Router();
+ 
+  router.get('/leaderboard', (req, res) => {
+    const limitParam = req.query.limit;
+    const token = req.query.token as string | undefined;
+ 
+    let limit = 50;
+    if (limitParam !== undefined) {
+      const parsed = parseInt(limitParam as string, 10);
+      if (isNaN(parsed) || parsed < 1) {
+        res.status(400).json({ error: 'Invalid limit parameter' });
+        return;
+      }
+      limit = Math.min(parsed, 100);
+    }
+ 
+    const entries: LeaderboardEntry[] = getLeaderboard(db, limit, token);
+    res.json(entries);
+  });
+ 
+  return router;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/api/routes/reputation.ts.html b/indexer/coverage/lcov-report/src/api/routes/reputation.ts.html new file mode 100644 index 00000000..9a68f3bc --- /dev/null +++ b/indexer/coverage/lcov-report/src/api/routes/reputation.ts.html @@ -0,0 +1,412 @@ + + + + + + Code coverage report for src/api/routes/reputation.ts + + + + + + + + + +
+
+

All files / src/api/routes reputation.ts

+
+ +
+ 100% + Statements + 23/23 +
+ + +
+ 100% + Branches + 9/9 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 23/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +42x +  +42x +9x +9x +  +9x +  +  +  +  +  +  +  +  +  +  +  +9x +1x +  +  +  +  +  +  +  +1x +  +  +8x +8x +1x +7x +1x +  +  +8x +8x +1x +7x +1x +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +  +  +  +13x +  +  +  +  +  +  +  +8x +  +  +42x +  + 
import { Router } from 'express';
+import type Database from 'better-sqlite3';
+ 
+interface ReputationUpdateRow {
+  new_score: number;
+  invoices_submitted: number;
+  invoices_paid: number;
+  invoices_defaulted: number;
+  ledger: number;
+  timestamp: number;
+  event_type: string;
+}
+ 
+interface HistoryEntry {
+  ledger: number;
+  score: number;
+  eventType: string;
+  timestamp: number;
+}
+ 
+interface ReputationResponse {
+  score: number;
+  invoicesPaid: number;
+  invoicesDefaulted: number;
+  invoicesSubmitted: number;
+  lastActivityLedger: number;
+  history: HistoryEntry[];
+}
+ 
+export function createReputationRouter(db: Database.Database): Router {
+  const router = Router();
+ 
+  router.get('/reputation/:address', (req, res) => {
+    const { address } = req.params;
+    const historyPeriod = (req.query.historyPeriod as string) || 'all';
+ 
+    const latestRow = db
+      .prepare(
+        `
+        SELECT new_score, invoices_submitted, invoices_paid, invoices_defaulted, ledger
+        FROM reputation_updates
+        WHERE address = ?
+        ORDER BY id DESC
+        LIMIT 1
+      `
+      )
+      .get(address) as ReputationUpdateRow | undefined;
+ 
+    if (!latestRow) {
+      res.json({
+        score: 0,
+        invoicesPaid: 0,
+        invoicesDefaulted: 0,
+        invoicesSubmitted: 0,
+        lastActivityLedger: 0,
+        history: [],
+      });
+      return;
+    }
+ 
+    let dateFilter = '';
+    if (historyPeriod === '30d') {
+      dateFilter = 'AND timestamp >= ?';
+    } else if (historyPeriod === '90d') {
+      dateFilter = 'AND timestamp >= ?';
+    }
+ 
+    let historyParams: (string | number)[] = [address];
+    if (historyPeriod === '30d') {
+      historyParams.push(Math.floor(Date.now() / 1000) - 30 * 24 * 60 * 60);
+    } else if (historyPeriod === '90d') {
+      historyParams.push(Math.floor(Date.now() / 1000) - 90 * 24 * 60 * 60);
+    }
+ 
+    const historyRows = db
+      .prepare(
+        `
+        SELECT new_score, ledger, event_type, timestamp
+        FROM reputation_updates
+        WHERE address = ? ${dateFilter}
+        ORDER BY timestamp ASC
+      `
+      )
+      .all(...historyParams) as Array<{
+      new_score: number;
+      ledger: number;
+      event_type: string;
+      timestamp: number;
+    }>;
+ 
+    const response: ReputationResponse = {
+      score: latestRow.new_score,
+      invoicesPaid: latestRow.invoices_paid,
+      invoicesDefaulted: latestRow.invoices_defaulted,
+      invoicesSubmitted: latestRow.invoices_submitted,
+      lastActivityLedger: latestRow.ledger,
+      history: historyRows.map((row) => ({
+        ledger: row.ledger,
+        score: row.new_score,
+        eventType: row.event_type,
+        timestamp: row.timestamp,
+      })),
+    };
+ 
+    res.json(response);
+  });
+ 
+  return router;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/api/routes/stats.ts.html b/indexer/coverage/lcov-report/src/api/routes/stats.ts.html new file mode 100644 index 00000000..ce224cdd --- /dev/null +++ b/indexer/coverage/lcov-report/src/api/routes/stats.ts.html @@ -0,0 +1,172 @@ + + + + + + Code coverage report for src/api/routes/stats.ts + + + + + + + + + +
+
+

All files / src/api/routes stats.ts

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 66.66% + Branches + 2/3 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30  +  +  +  +  +  +  +  +  +  +42x +  +42x +7x +7x +  +  +42x +3x +3x +1x +1x +  +2x +2x +  +  +42x +  + 
import { Router } from 'express';
+import type Database from 'better-sqlite3';
+import {
+  getProtocolStats,
+  getStatsHistory,
+  type ProtocolStats,
+  type StatsHistoryEntry,
+} from '../../services/statsService.js';
+ 
+export function createStatsRouter(db: Database.Database): Router {
+  const router = Router();
+ 
+  router.get('/stats', (_req, res) => {
+    const stats: ProtocolStats = getProtocolStats(db);
+    res.json(stats);
+  });
+ 
+  router.get('/stats/history', (req, res) => {
+    const period = (req.query.period as string) || '30d';
+    if (!['30d', '90d', 'all'].includes(period)) {
+      res.status(400).json({ error: 'Invalid period. Use 30d, 90d, or all' });
+      return;
+    }
+    const history: StatsHistoryEntry[] = getStatsHistory(db, period as '30d' | '90d' | 'all');
+    res.json(history);
+  });
+ 
+  return router;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/app.ts.html b/indexer/coverage/lcov-report/src/app.ts.html new file mode 100644 index 00000000..013774ba --- /dev/null +++ b/indexer/coverage/lcov-report/src/app.ts.html @@ -0,0 +1,160 @@ + + + + + + Code coverage report for src/app.ts + + + + + + + + + +
+
+

All files / src app.ts

+
+ +
+ 90% + Statements + 9/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 90% + Lines + 9/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26  +  +  +  +  +  +  +  +  +42x +  +42x +  +42x +42x +42x +42x +42x +  +42x +  +  +  +42x +  + 
import express from 'express';
+import type Database from 'better-sqlite3';
+import { createLeaderboardRouter } from './api/routes/leaderboard.js';
+import { createReputationRouter } from './api/routes/reputation.js';
+import { createStatsRouter } from './api/routes/stats.js';
+import { createInvoicesRouter } from './api/routes/invoices.js';
+import { createEventsRouter } from './api/routes/events.js';
+ 
+export function createApp(db: Database.Database): express.Express {
+  const app = express();
+ 
+  app.use(express.json());
+ 
+  app.use(createLeaderboardRouter(db));
+  app.use(createReputationRouter(db));
+  app.use(createStatsRouter(db));
+  app.use(createInvoicesRouter(db));
+  app.use(createEventsRouter(db));
+ 
+  app.get('/health', (_req, res) => {
+    res.json({ status: 'ok' });
+  });
+ 
+  return app;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/config.ts.html b/indexer/coverage/lcov-report/src/config.ts.html new file mode 100644 index 00000000..78f3ef06 --- /dev/null +++ b/indexer/coverage/lcov-report/src/config.ts.html @@ -0,0 +1,106 @@ + + + + + + Code coverage report for src/config.ts + + + + + + + + + +
+
+

All files / src config.ts

+
+ +
+ 0% + Statements + 0/1 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8  +  +  +  +  +  +  + 
export const config = {
+  port: parseInt(process.env.PORT || '3001', 10),
+  dbPath: process.env.DB_PATH || './indexer.db',
+  cacheTtlMs: parseInt(process.env.CACHE_TTL_MS || '60000', 10),
+  maxLeaderboardLimit: 100,
+  defaultLeaderboardLimit: 50,
+};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/database/db.ts.html b/indexer/coverage/lcov-report/src/database/db.ts.html new file mode 100644 index 00000000..9bf5e2d8 --- /dev/null +++ b/indexer/coverage/lcov-report/src/database/db.ts.html @@ -0,0 +1,160 @@ + + + + + + Code coverage report for src/database/db.ts + + + + + + + + + +
+
+

All files / src/database db.ts

+
+ +
+ 0% + Statements + 0/11 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 0% + Lines + 0/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import Database from 'better-sqlite3';
+import { initializeSchema } from './schema.js';
+ 
+let db: Database.Database | null = null;
+ 
+export function getDb(dbPath?: string): Database.Database {
+  Iif (!db) {
+    db = new Database(dbPath || ':memory:');
+    db.pragma('journal_mode = WAL');
+    db.pragma('foreign_keys = ON');
+    initializeSchema(db);
+  }
+  return db;
+}
+ 
+export function closeDb(): void {
+  Iif (db) {
+    db.close();
+    db = null;
+  }
+}
+ 
+export function resetDb(): void {
+  closeDb();
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/database/index.html b/indexer/coverage/lcov-report/src/database/index.html new file mode 100644 index 00000000..ec261a5f --- /dev/null +++ b/indexer/coverage/lcov-report/src/database/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/database + + + + + + + + + +
+
+

All files src/database

+
+ +
+ 8.33% + Statements + 1/12 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 25% + Functions + 1/4 +
+ + +
+ 8.33% + Lines + 1/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
db.ts +
+
0%0/110%0/40%0/30%0/11
schema.ts +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/database/schema.ts.html b/indexer/coverage/lcov-report/src/database/schema.ts.html new file mode 100644 index 00000000..a160396f --- /dev/null +++ b/indexer/coverage/lcov-report/src/database/schema.ts.html @@ -0,0 +1,325 @@ + + + + + + Code coverage report for src/database/schema.ts + + + + + + + + + +
+
+

All files / src/database schema.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81  +  +  +42x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type Database from 'better-sqlite3';
+ 
+export function initializeSchema(db: Database.Database): void {
+  db.exec(`
+    CREATE TABLE IF NOT EXISTS invoices (
+      id INTEGER PRIMARY KEY,
+      freelancer TEXT NOT NULL,
+      payer TEXT NOT NULL,
+      token TEXT NOT NULL,
+      amount TEXT NOT NULL,
+      due_date INTEGER NOT NULL,
+      discount_rate INTEGER NOT NULL,
+      status TEXT NOT NULL DEFAULT 'Pending',
+      funder TEXT,
+      funded_at INTEGER,
+      amount_funded TEXT NOT NULL DEFAULT '0',
+      amount_paid TEXT NOT NULL DEFAULT '0',
+      referral_code TEXT,
+      submitter_reputation INTEGER NOT NULL DEFAULT 0,
+      created_at INTEGER NOT NULL
+    );
+ 
+    CREATE TABLE IF NOT EXISTS events (
+      id INTEGER PRIMARY KEY AUTOINCREMENT,
+      invoice_id INTEGER NOT NULL,
+      event_type TEXT NOT NULL,
+      ledger INTEGER NOT NULL,
+      timestamp INTEGER NOT NULL,
+      data TEXT NOT NULL DEFAULT '{}',
+      FOREIGN KEY (invoice_id) REFERENCES invoices(id)
+    );
+ 
+    CREATE TABLE IF NOT EXISTS reputation_updates (
+      id INTEGER PRIMARY KEY,
+      address TEXT NOT NULL,
+      event_type TEXT NOT NULL DEFAULT 'reputation_updated',
+      old_score INTEGER NOT NULL DEFAULT 0,
+      new_score INTEGER NOT NULL DEFAULT 0,
+      invoices_submitted INTEGER NOT NULL DEFAULT 0,
+      invoices_paid INTEGER NOT NULL DEFAULT 0,
+      invoices_defaulted INTEGER NOT NULL DEFAULT 0,
+      ledger INTEGER NOT NULL,
+      timestamp INTEGER NOT NULL
+    );
+ 
+    CREATE TABLE IF NOT EXISTS stats_snapshots (
+      id INTEGER PRIMARY KEY AUTOINCREMENT,
+      total_invoices INTEGER NOT NULL DEFAULT 0,
+      total_funded INTEGER NOT NULL DEFAULT 0,
+      total_paid INTEGER NOT NULL DEFAULT 0,
+      total_cancelled INTEGER NOT NULL DEFAULT 0,
+      total_expired INTEGER NOT NULL DEFAULT 0,
+      total_disputed INTEGER NOT NULL DEFAULT 0,
+      volume_by_token TEXT NOT NULL DEFAULT '{}',
+      avg_discount_rate_bps REAL NOT NULL DEFAULT 0,
+      dispute_rate REAL NOT NULL DEFAULT 0,
+      last_updated_at INTEGER NOT NULL
+    );
+ 
+    CREATE TABLE IF NOT EXISTS stats_history (
+      id INTEGER PRIMARY KEY AUTOINCREMENT,
+      date TEXT NOT NULL,
+      total_invoices INTEGER NOT NULL DEFAULT 0,
+      total_funded INTEGER NOT NULL DEFAULT 0,
+      total_paid INTEGER NOT NULL DEFAULT 0,
+      total_volume TEXT NOT NULL DEFAULT '0',
+      avg_discount_rate_bps REAL NOT NULL DEFAULT 0
+    );
+ 
+    CREATE INDEX IF NOT EXISTS idx_events_invoice_id ON events(invoice_id);
+    CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
+    CREATE INDEX IF NOT EXISTS idx_reputation_address ON reputation_updates(address);
+    CREATE INDEX IF NOT EXISTS idx_reputation_timestamp ON reputation_updates(timestamp);
+    CREATE INDEX IF NOT EXISTS idx_invoices_status ON invoices(status);
+    CREATE INDEX IF NOT EXISTS idx_stats_history_date ON stats_history(date);
+    CREATE INDEX IF NOT EXISTS idx_invoices_freelancer ON invoices(freelancer);
+    CREATE INDEX IF NOT EXISTS idx_invoices_payer ON invoices(payer);
+    CREATE INDEX IF NOT EXISTS idx_invoices_funder ON invoices(funder);
+  `);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/index.html b/indexer/coverage/lcov-report/src/index.html new file mode 100644 index 00000000..93f4caa1 --- /dev/null +++ b/indexer/coverage/lcov-report/src/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 81.81% + Statements + 9/11 +
+ + +
+ 0% + Branches + 0/6 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 81.81% + Lines + 9/11 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
app.ts +
+
90%9/10100%0/050%1/290%9/10
config.ts +
+
0%0/10%0/6100%0/00%0/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/services/index.html b/indexer/coverage/lcov-report/src/services/index.html new file mode 100644 index 00000000..2387f2d9 --- /dev/null +++ b/indexer/coverage/lcov-report/src/services/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/services + + + + + + + + + +
+
+

All files src/services

+
+ +
+ 87.09% + Statements + 27/31 +
+ + +
+ 86.2% + Branches + 25/29 +
+ + +
+ 83.33% + Functions + 5/6 +
+ + +
+ 87.09% + Lines + 27/31 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
leaderboardService.ts +
+
87.5%7/860%3/5100%2/287.5%7/8
statsService.ts +
+
86.95%20/2391.66%22/2475%3/486.95%20/23
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/services/leaderboardService.ts.html b/indexer/coverage/lcov-report/src/services/leaderboardService.ts.html new file mode 100644 index 00000000..39d041df --- /dev/null +++ b/indexer/coverage/lcov-report/src/services/leaderboardService.ts.html @@ -0,0 +1,349 @@ + + + + + + Code coverage report for src/services/leaderboardService.ts + + + + + + + + + +
+
+

All files / src/services leaderboardService.ts

+
+ +
+ 87.5% + Statements + 7/8 +
+ + +
+ 60% + Branches + 3/5 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 87.5% + Lines + 7/8 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +7x +16x +16x +  +  +  +  +  +  +  +  +  + 
import type Database from 'better-sqlite3';
+ 
+export interface LeaderboardEntry {
+  rank: number;
+  address: string;
+  score: number;
+  invoicesPaid: number;
+  invoicesDefaulted: number;
+  totalVolume: string;
+}
+ 
+interface ReputationRow {
+  address: string;
+  new_score: number;
+  invoices_paid: number;
+  invoices_defaulted: number;
+}
+ 
+export function getLeaderboard(
+  db: Database.Database,
+  limit: number = 50,
+  token?: string
+): LeaderboardEntry[] {
+  const safeLimit = Math.min(Math.max(1, limit), 100);
+ 
+  let rows: ReputationRow[];
+ 
+  Iif (token) {
+    rows = db
+      .prepare(
+        `
+        SELECT
+          r.address,
+          r.new_score,
+          r.invoices_paid,
+          r.invoices_defaulted
+        FROM reputation_updates r
+        WHERE r.id IN (
+          SELECT MAX(id) FROM reputation_updates GROUP BY address
+        )
+        AND r.address IN (
+          SELECT DISTINCT payer FROM invoices WHERE token = ?
+        )
+        ORDER BY r.new_score DESC
+        LIMIT ?
+      `
+      )
+      .all(token, safeLimit) as ReputationRow[];
+  } else {
+    rows = db
+      .prepare(
+        `
+        SELECT
+          r.address,
+          r.new_score,
+          r.invoices_paid,
+          r.invoices_defaulted
+        FROM reputation_updates r
+        WHERE r.id IN (
+          SELECT MAX(id) FROM reputation_updates GROUP BY address
+        )
+        ORDER BY r.new_score DESC
+        LIMIT ?
+      `
+      )
+      .all(safeLimit) as ReputationRow[];
+  }
+ 
+  const volumeStmt = db.prepare(
+    `SELECT COALESCE(SUM(CAST(amount_paid AS INTEGER)), 0) as vol
+     FROM events e
+     JOIN invoices i ON e.invoice_id = i.id
+     WHERE e.event_type = 'paid' AND e.data LIKE '%"payer":"%'
+     AND json_extract(e.data, '$.payer') = ?`
+  );
+ 
+  return rows.map((row, idx) => {
+    const volResult = volumeStmt.get(row.address) as { vol: number } | undefined;
+    return {
+      rank: idx + 1,
+      address: row.address,
+      score: row.new_score,
+      invoicesPaid: row.invoices_paid,
+      invoicesDefaulted: row.invoices_defaulted,
+      totalVolume: String(volResult?.vol || 0),
+    };
+  });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov-report/src/services/statsService.ts.html b/indexer/coverage/lcov-report/src/services/statsService.ts.html new file mode 100644 index 00000000..78902fff --- /dev/null +++ b/indexer/coverage/lcov-report/src/services/statsService.ts.html @@ -0,0 +1,502 @@ + + + + + + Code coverage report for src/services/statsService.ts + + + + + + + + + +
+
+

All files / src/services statsService.ts

+
+ +
+ 86.95% + Statements + 20/23 +
+ + +
+ 91.66% + Branches + 22/24 +
+ + +
+ 75% + Functions + 3/4 +
+ + +
+ 86.95% + Lines + 20/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +7x +  +7x +1x +  +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6x +  +  +  +  +  +  +  +  +  +  +6x +6x +6x +  +  +6x +  +6x +  +  +  +  +  +  +  +  +  +  +  +  +6x +6x +  +  +  +  +  +  +2x +2x +1x +1x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +9x +  + 
import type Database from 'better-sqlite3';
+ 
+export interface ProtocolStats {
+  totalInvoices: number;
+  totalFunded: number;
+  totalPaid: number;
+  totalCancelled: number;
+  totalExpired: number;
+  totalDisputed: number;
+  volumeByToken: Record<string, string>;
+  avgDiscountRateBps: number;
+  disputeRate: number;
+  lastUpdatedAt: number;
+}
+ 
+export interface StatsHistoryEntry {
+  date: string;
+  totalInvoices: number;
+  totalFunded: number;
+  totalPaid: number;
+  totalVolume: string;
+  avgDiscountRateBps: number;
+}
+ 
+interface CachedStats {
+  stats: ProtocolStats;
+  cachedAt: number;
+}
+ 
+let cachedStats: CachedStats | null = null;
+ 
+export function getProtocolStats(
+  db: Database.Database,
+  cacheTtlMs: number = 60000
+): ProtocolStats {
+  const now = Date.now();
+ 
+  if (cachedStats && now - cachedStats.cachedAt < cacheTtlMs) {
+    return cachedStats.stats;
+  }
+ 
+  const counts = db
+    .prepare(
+      `
+      SELECT
+        COUNT(*) as total,
+        SUM(CASE WHEN status = 'Funded' OR status = 'Paid' OR status = 'Defaulted' THEN 1 ELSE 0 END) as funded,
+        SUM(CASE WHEN status = 'Paid' THEN 1 ELSE 0 END) as paid,
+        SUM(CASE WHEN status = 'Cancelled' THEN 1 ELSE 0 END) as cancelled,
+        SUM(CASE WHEN status = 'Expired' THEN 1 ELSE 0 END) as expired,
+        SUM(CASE WHEN status = 'Disputed' THEN 1 ELSE 0 END) as disputed,
+        AVG(CAST(discount_rate AS REAL)) as avg_discount
+      FROM invoices
+    `
+    )
+    .get() as {
+    total: number;
+    funded: number;
+    paid: number;
+    cancelled: number;
+    expired: number;
+    disputed: number;
+    avg_discount: number;
+  };
+ 
+  const tokenVolumes = db
+    .prepare(
+      `
+      SELECT token, COALESCE(SUM(CAST(amount_paid AS INTEGER)), 0) as volume
+      FROM invoices
+      WHERE CAST(amount_paid AS INTEGER) > 0
+      GROUP BY token
+    `
+    )
+    .all() as Array<{ token: string; volume: number }>;
+ 
+  const volumeByToken: Record<string, string> = {};
+  for (const row of tokenVolumes) {
+    volumeByToken[row.token] = String(row.volume);
+  }
+ 
+  const disputeRate = counts.total > 0 ? counts.disputed / counts.total : 0;
+ 
+  const stats: ProtocolStats = {
+    totalInvoices: counts.total || 0,
+    totalFunded: counts.funded || 0,
+    totalPaid: counts.paid || 0,
+    totalCancelled: counts.cancelled || 0,
+    totalExpired: counts.expired || 0,
+    totalDisputed: counts.disputed || 0,
+    volumeByToken,
+    avgDiscountRateBps: Math.round(counts.avg_discount || 0),
+    disputeRate: Math.round(disputeRate * 10000) / 10000,
+    lastUpdatedAt: now,
+  };
+ 
+  cachedStats = { stats, cachedAt: now };
+  return stats;
+}
+ 
+export function getStatsHistory(
+  db: Database.Database,
+  period: '30d' | '90d' | 'all' = '30d'
+): StatsHistoryEntry[] {
+  let dateFilter = '';
+  if (period === '30d') {
+    dateFilter = "WHERE date >= date('now', '-30 days')";
+  } else Iif (period === '90d') {
+    dateFilter = "WHERE date >= date('now', '-90 days')";
+  }
+ 
+  const rows = db
+    .prepare(
+      `
+      SELECT
+        date,
+        total_invoices,
+        total_funded,
+        total_paid,
+        total_volume,
+        avg_discount_rate_bps
+      FROM stats_history
+      ${dateFilter}
+      ORDER BY date ASC
+    `
+    )
+    .all() as StatsHistoryEntry[];
+ 
+  return rows;
+}
+ 
+export function refreshStats(db: Database.Database): ProtocolStats {
+  cachedStats = null;
+  return getProtocolStats(db);
+}
+ 
+export function clearStatsCache(): void {
+  cachedStats = null;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/indexer/coverage/lcov.info b/indexer/coverage/lcov.info new file mode 100644 index 00000000..38ce9e19 --- /dev/null +++ b/indexer/coverage/lcov.info @@ -0,0 +1,456 @@ +TN: +SF:src/app.ts +FN:9,createApp +FN:20,(anonymous_1) +FNF:2 +FNH:1 +FNDA:42,createApp +FNDA:0,(anonymous_1) +DA:10,42 +DA:12,42 +DA:14,42 +DA:15,42 +DA:16,42 +DA:17,42 +DA:18,42 +DA:20,42 +DA:21,0 +DA:24,42 +LF:10 +LH:9 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/config.ts +FNF:0 +FNH:0 +DA:1,0 +LF:1 +LH:0 +BRDA:2,0,0,0 +BRDA:2,0,1,0 +BRDA:3,1,0,0 +BRDA:3,1,1,0 +BRDA:4,2,0,0 +BRDA:4,2,1,0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:src/api/routes/events.ts +FN:16,createEventsRouter +FN:19,(anonymous_1) +FN:36,(anonymous_2) +FN:64,(anonymous_3) +FNF:4 +FNH:4 +FNDA:42,createEventsRouter +FNDA:5,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:6,(anonymous_3) +DA:17,42 +DA:19,42 +DA:20,5 +DA:21,5 +DA:22,5 +DA:23,5 +DA:24,5 +DA:26,5 +DA:27,1 +DA:28,1 +DA:31,4 +DA:32,4 +DA:34,4 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,4 +DA:44,4 +DA:50,4 +DA:51,4 +DA:54,4 +DA:62,4 +DA:64,6 +DA:73,4 +DA:81,42 +LF:26 +LH:26 +BRDA:22,0,0,5 +BRDA:22,0,1,4 +BRDA:23,1,0,5 +BRDA:23,1,1,4 +BRDA:26,2,0,1 +BRDA:34,3,0,1 +BRDA:41,4,0,4 +BRDA:41,4,1,0 +BRDA:51,5,0,4 +BRDA:51,5,1,0 +BRDA:70,6,0,6 +BRDA:70,6,1,0 +BRF:12 +BRH:9 +end_of_record +TN: +SF:src/api/routes/invoices.ts +FN:56,computeEffectiveYieldBps +FN:64,createInvoicesRouter +FN:67,(anonymous_2) +FN:122,(anonymous_3) +FN:133,(anonymous_4) +FN:187,(anonymous_5) +FNF:6 +FNH:6 +FNDA:12,computeEffectiveYieldBps +FNDA:42,createInvoicesRouter +FNDA:10,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:3,(anonymous_4) +FNDA:4,(anonymous_5) +DA:57,12 +DA:58,12 +DA:59,12 +DA:60,12 +DA:61,12 +DA:65,42 +DA:67,42 +DA:68,10 +DA:69,10 +DA:70,1 +DA:71,1 +DA:74,9 +DA:78,9 +DA:79,1 +DA:80,1 +DA:83,8 +DA:87,8 +DA:92,8 +DA:93,8 +DA:95,8 +DA:97,8 +DA:98,8 +DA:103,8 +DA:122,4 +DA:130,8 +DA:133,42 +DA:134,3 +DA:136,3 +DA:137,3 +DA:138,3 +DA:140,3 +DA:141,3 +DA:142,3 +DA:144,3 +DA:145,3 +DA:147,3 +DA:154,3 +DA:155,3 +DA:157,3 +DA:158,3 +DA:160,3 +DA:161,1 +DA:162,1 +DA:164,3 +DA:165,1 +DA:166,1 +DA:168,3 +DA:169,1 +DA:170,1 +DA:173,3 +DA:175,3 +DA:176,3 +DA:177,3 +DA:179,3 +DA:185,3 +DA:187,3 +DA:188,4 +DA:192,4 +DA:193,4 +DA:195,4 +DA:196,4 +DA:197,4 +DA:202,4 +DA:224,3 +DA:232,42 +LF:65 +LH:65 +BRDA:59,0,0,0 +BRDA:69,1,0,1 +BRDA:78,2,0,1 +BRDA:92,3,0,8 +BRDA:92,3,1,0 +BRDA:93,4,0,8 +BRDA:93,4,1,0 +BRDA:95,5,0,0 +BRDA:95,5,1,8 +BRDA:126,6,0,4 +BRDA:126,6,1,0 +BRDA:140,7,0,3 +BRDA:140,7,1,2 +BRDA:141,8,0,3 +BRDA:141,8,1,2 +BRDA:144,9,0,3 +BRDA:144,9,1,2 +BRDA:145,10,0,3 +BRDA:145,10,1,2 +BRDA:154,11,0,3 +BRDA:154,11,1,0 +BRDA:155,12,0,1 +BRDA:155,12,1,2 +BRDA:160,13,0,1 +BRDA:164,14,0,1 +BRDA:168,15,0,1 +BRDA:173,16,0,1 +BRDA:173,16,1,2 +BRDA:177,17,0,3 +BRDA:177,17,1,0 +BRDA:192,18,0,4 +BRDA:192,18,1,0 +BRDA:193,19,0,4 +BRDA:193,19,1,0 +BRDA:195,20,0,0 +BRDA:195,20,1,4 +BRF:36 +BRH:26 +end_of_record +TN: +SF:src/api/routes/leaderboard.ts +FN:5,createLeaderboardRouter +FN:8,(anonymous_1) +FNF:2 +FNH:2 +FNDA:42,createLeaderboardRouter +FNDA:8,(anonymous_1) +DA:6,42 +DA:8,42 +DA:9,8 +DA:10,8 +DA:12,8 +DA:13,8 +DA:14,3 +DA:15,3 +DA:16,1 +DA:17,1 +DA:19,2 +DA:22,7 +DA:23,7 +DA:26,42 +LF:14 +LH:14 +BRDA:13,0,0,3 +BRDA:15,1,0,1 +BRDA:15,2,0,3 +BRDA:15,2,1,2 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/api/routes/reputation.ts +FN:30,createReputationRouter +FN:33,(anonymous_1) +FN:97,(anonymous_2) +FNF:3 +FNH:3 +FNDA:42,createReputationRouter +FNDA:9,(anonymous_1) +FNDA:13,(anonymous_2) +DA:31,42 +DA:33,42 +DA:34,9 +DA:35,9 +DA:37,9 +DA:49,9 +DA:50,1 +DA:58,1 +DA:61,8 +DA:62,8 +DA:63,1 +DA:64,7 +DA:65,1 +DA:68,8 +DA:69,8 +DA:70,1 +DA:71,7 +DA:72,1 +DA:75,8 +DA:91,8 +DA:97,13 +DA:105,8 +DA:108,42 +LF:23 +LH:23 +BRDA:35,0,0,9 +BRDA:35,0,1,6 +BRDA:49,1,0,1 +BRDA:62,2,0,1 +BRDA:62,2,1,7 +BRDA:64,3,0,1 +BRDA:69,4,0,1 +BRDA:69,4,1,7 +BRDA:71,5,0,1 +BRF:9 +BRH:9 +end_of_record +TN: +SF:src/api/routes/stats.ts +FN:10,createStatsRouter +FN:13,(anonymous_1) +FN:18,(anonymous_2) +FNF:3 +FNH:3 +FNDA:42,createStatsRouter +FNDA:7,(anonymous_1) +FNDA:3,(anonymous_2) +DA:11,42 +DA:13,42 +DA:14,7 +DA:15,7 +DA:18,42 +DA:19,3 +DA:20,3 +DA:21,1 +DA:22,1 +DA:24,2 +DA:25,2 +DA:28,42 +LF:12 +LH:12 +BRDA:19,0,0,3 +BRDA:19,0,1,0 +BRDA:20,1,0,1 +BRF:3 +BRH:2 +end_of_record +TN: +SF:src/database/db.ts +FN:6,getDb +FN:16,closeDb +FN:23,resetDb +FNF:3 +FNH:0 +FNDA:0,getDb +FNDA:0,closeDb +FNDA:0,resetDb +DA:4,0 +DA:7,0 +DA:8,0 +DA:9,0 +DA:10,0 +DA:11,0 +DA:13,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:24,0 +LF:11 +LH:0 +BRDA:7,0,0,0 +BRDA:8,1,0,0 +BRDA:8,1,1,0 +BRDA:17,2,0,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/database/schema.ts +FN:3,initializeSchema +FNF:1 +FNH:1 +FNDA:42,initializeSchema +DA:4,42 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/services/leaderboardService.ts +FN:19,getLeaderboard +FN:77,(anonymous_1) +FNF:2 +FNH:2 +FNDA:7,getLeaderboard +FNDA:16,(anonymous_1) +DA:24,7 +DA:28,7 +DA:29,0 +DA:50,7 +DA:69,7 +DA:77,7 +DA:78,16 +DA:79,16 +LF:8 +LH:7 +BRDA:21,0,0,0 +BRDA:28,1,0,0 +BRDA:28,1,1,7 +BRDA:85,2,0,16 +BRDA:85,2,1,16 +BRF:5 +BRH:3 +end_of_record +TN: +SF:src/services/statsService.ts +FN:32,getProtocolStats +FN:101,getStatsHistory +FN:132,refreshStats +FN:137,clearStatsCache +FNF:4 +FNH:3 +FNDA:7,getProtocolStats +FNDA:2,getStatsHistory +FNDA:0,refreshStats +FNDA:9,clearStatsCache +DA:30,5 +DA:36,7 +DA:38,7 +DA:39,1 +DA:42,6 +DA:66,6 +DA:77,6 +DA:78,6 +DA:79,6 +DA:82,6 +DA:84,6 +DA:97,6 +DA:98,6 +DA:105,2 +DA:106,2 +DA:107,1 +DA:108,1 +DA:109,0 +DA:112,2 +DA:129,2 +DA:133,0 +DA:134,0 +DA:138,9 +LF:23 +LH:20 +BRDA:34,0,0,7 +BRDA:38,1,0,1 +BRDA:38,2,0,7 +BRDA:38,2,1,1 +BRDA:82,3,0,4 +BRDA:82,3,1,2 +BRDA:85,4,0,6 +BRDA:85,4,1,2 +BRDA:86,5,0,6 +BRDA:86,5,1,2 +BRDA:87,6,0,6 +BRDA:87,6,1,2 +BRDA:88,7,0,6 +BRDA:88,7,1,5 +BRDA:89,8,0,6 +BRDA:89,8,1,5 +BRDA:90,9,0,6 +BRDA:90,9,1,4 +BRDA:92,10,0,6 +BRDA:92,10,1,2 +BRDA:103,11,0,0 +BRDA:106,12,0,1 +BRDA:106,12,1,1 +BRDA:108,13,0,0 +BRF:24 +BRH:22 +end_of_record diff --git a/indexer/src/api/routes/events.ts b/indexer/src/api/routes/events.ts new file mode 100644 index 00000000..e251457d --- /dev/null +++ b/indexer/src/api/routes/events.ts @@ -0,0 +1,82 @@ +import { Router } from 'express'; +import type Database from 'better-sqlite3'; + +interface EventRow { + id: number; + invoice_id: number; + event_type: string; + ledger: number; + timestamp: number; + data: string; + freelancer: string; + payer: string; + funder: string | null; +} + +export function createEventsRouter(db: Database.Database): Router { + const router = Router(); + + router.get('/events', (req, res) => { + const address = req.query.address as string; + const typesStr = req.query.types as string | undefined; + const page = Math.max(1, parseInt(req.query.page as string || '1', 10)); + const pageSize = Math.max(1, parseInt(req.query.pageSize as string || '20', 10)); + const offset = (page - 1) * pageSize; + + if (!address) { + res.status(400).json({ error: 'Address parameter is required' }); + return; + } + + const conditions: string[] = ['(i.freelancer = ? OR i.payer = ? OR i.funder = ?)']; + const params: any[] = [address, address, address]; + + if (typesStr) { + const types = typesStr.split(','); + const placeHolders = types.map(() => '?').join(','); + conditions.push(`e.event_type IN (${placeHolders})`); + params.push(...types); + } + + const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''; + + // Count query + const countQuery = ` + SELECT COUNT(*) as total + FROM events e + JOIN invoices i ON e.invoice_id = i.id + ${whereClause} + `; + const totalRow = db.prepare(countQuery).get(...params) as { total: number }; + const total = totalRow ? totalRow.total : 0; + + // Select query + const selectQuery = ` + SELECT e.*, i.freelancer, i.payer, i.funder + FROM events e + JOIN invoices i ON e.invoice_id = i.id + ${whereClause} + ORDER BY e.timestamp DESC, e.id DESC + LIMIT ? OFFSET ? + `; + const rows = db.prepare(selectQuery).all(...params, pageSize, offset) as EventRow[]; + + const events = rows.map(r => ({ + id: r.id, + invoiceId: r.invoice_id, + type: r.event_type, + ledger: r.ledger, + timestamp: r.timestamp, + data: JSON.parse(r.data || '{}'), + })); + + res.json({ + events, + total, + page, + pageSize + }); + }); + + return router; +} diff --git a/indexer/src/api/routes/invoices.ts b/indexer/src/api/routes/invoices.ts index 2330855f..fb7787db 100644 --- a/indexer/src/api/routes/invoices.ts +++ b/indexer/src/api/routes/invoices.ts @@ -130,5 +130,104 @@ export function createInvoicesRouter(db: Database.Database): Router { res.json(response); }); + router.get('/invoices', (req, res) => { + res.setHeader('Cache-Control', 'max-age=10'); + + const state = req.query.state as string | undefined; + const token = req.query.token as string | undefined; + const submitter = req.query.submitter as string | undefined; + + const page = Math.max(1, parseInt(req.query.page as string || '1', 10)); + const pageSize = Math.max(1, parseInt(req.query.pageSize as string || '20', 10)); + const offset = (page - 1) * pageSize; + + const sortByParam = req.query.sortBy as string || 'createdAt'; + const sortOrderParam = (req.query.sortOrder as string || 'desc').toLowerCase(); + + const sortFieldMap: Record = { + createdAt: 'created_at', + dueDate: 'due_date', + amount: 'CAST(amount AS REAL)', + discountRate: 'discount_rate' + }; + + const orderBy = sortFieldMap[sortByParam] || 'created_at'; + const order = sortOrderParam === 'asc' ? 'ASC' : 'DESC'; + + const conditions: string[] = []; + const params: any[] = []; + + if (state) { + conditions.push('status = ?'); + params.push(state); + } + if (token) { + conditions.push('token = ?'); + params.push(token); + } + if (submitter) { + conditions.push('freelancer = ?'); + params.push(submitter); + } + + const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''; + + const countQuery = `SELECT COUNT(*) as total FROM invoices ${whereClause}`; + const totalRow = db.prepare(countQuery).get(...params) as { total: number }; + const total = totalRow ? totalRow.total : 0; + + const selectQuery = ` + SELECT * FROM invoices + ${whereClause} + ORDER BY ${orderBy} ${order} + LIMIT ? OFFSET ? + `; + const rows = db.prepare(selectQuery).all(...params, pageSize, offset) as InvoiceRow[]; + + const invoices = rows.map((invoice) => { + const effectiveYieldBps = computeEffectiveYieldBps( + invoice.discount_rate, + invoice.due_date + ); + const amountFunded = BigInt(invoice.amount_funded || '0'); + const amountPaid = BigInt(invoice.amount_paid || '0'); + const remainingBalance = + amountPaid > amountFunded ? '0' : String(amountFunded - amountPaid); + const now = Math.floor(Date.now() / 1000); + const daysUntilExpiry = Math.max( + 0, + Math.ceil((invoice.due_date - now) / (24 * 60 * 60)) + ); + + return { + id: invoice.id, + freelancer: invoice.freelancer, + payer: invoice.payer, + token: invoice.token, + amount: invoice.amount, + dueDate: invoice.due_date, + discountRate: invoice.discount_rate, + status: invoice.status, + funder: invoice.funder, + fundedAt: invoice.funded_at, + amountFunded: invoice.amount_funded, + amountPaid: invoice.amount_paid, + referralCode: invoice.referral_code, + submitterReputation: invoice.submitter_reputation, + createdAt: invoice.created_at, + effectiveYieldBps, + remainingBalance, + daysUntilExpiry, + }; + }); + + res.json({ + invoices, + total, + page, + pageSize + }); + }); + return router; } diff --git a/indexer/src/app.ts b/indexer/src/app.ts index 31774e68..8066d39c 100644 --- a/indexer/src/app.ts +++ b/indexer/src/app.ts @@ -4,6 +4,7 @@ import { createLeaderboardRouter } from './api/routes/leaderboard.js'; import { createReputationRouter } from './api/routes/reputation.js'; import { createStatsRouter } from './api/routes/stats.js'; import { createInvoicesRouter } from './api/routes/invoices.js'; +import { createEventsRouter } from './api/routes/events.js'; export function createApp(db: Database.Database): express.Express { const app = express(); @@ -14,6 +15,7 @@ export function createApp(db: Database.Database): express.Express { app.use(createReputationRouter(db)); app.use(createStatsRouter(db)); app.use(createInvoicesRouter(db)); + app.use(createEventsRouter(db)); app.get('/health', (_req, res) => { res.json({ status: 'ok' }); diff --git a/indexer/src/database/schema.ts b/indexer/src/database/schema.ts index e54d6088..a0119e6b 100644 --- a/indexer/src/database/schema.ts +++ b/indexer/src/database/schema.ts @@ -73,5 +73,8 @@ export function initializeSchema(db: Database.Database): void { CREATE INDEX IF NOT EXISTS idx_reputation_timestamp ON reputation_updates(timestamp); CREATE INDEX IF NOT EXISTS idx_invoices_status ON invoices(status); CREATE INDEX IF NOT EXISTS idx_stats_history_date ON stats_history(date); + CREATE INDEX IF NOT EXISTS idx_invoices_freelancer ON invoices(freelancer); + CREATE INDEX IF NOT EXISTS idx_invoices_payer ON invoices(payer); + CREATE INDEX IF NOT EXISTS idx_invoices_funder ON invoices(funder); `); } diff --git a/indexer/tests/events.test.ts b/indexer/tests/events.test.ts new file mode 100644 index 00000000..89065877 --- /dev/null +++ b/indexer/tests/events.test.ts @@ -0,0 +1,66 @@ +import request from 'supertest'; +import { + createTestDb, + seedInvoice, + seedEvent, + createTestApp, +} from './helpers.js'; + +describe('GET /events', () => { + let db: ReturnType; + let app: ReturnType; + + beforeEach(() => { + db = createTestDb(); + app = createTestApp(db); + }); + + afterEach(() => { + db.close(); + }); + + it('should return 400 if address is missing', async () => { + const res = await request(app).get('/events'); + expect(res.status).toBe(400); + expect(res.body.error).toBe('Address parameter is required'); + }); + + it('should return events where address is freelancer, payer, or funder', async () => { + seedInvoice(db, { id: 1, freelancer: 'GFREELANCER', payer: 'GPAYER', funder: 'GLP' }); + seedEvent(db, { invoice_id: 1, event_type: 'InvoiceFunded', ledger: 100, timestamp: 1000, data: '{}' }); + seedEvent(db, { invoice_id: 1, event_type: 'InvoicePaid', ledger: 101, timestamp: 1001, data: '{}' }); + + // Query for freelancer + let res = await request(app).get('/events?address=GFREELANCER'); + expect(res.status).toBe(200); + expect(res.body.events).toHaveLength(2); + expect(res.body.total).toBe(2); + + // Query for funder/LP + res = await request(app).get('/events?address=GLP'); + expect(res.status).toBe(200); + expect(res.body.events).toHaveLength(2); + }); + + it('should filter events by type', async () => { + seedInvoice(db, { id: 1, freelancer: 'GFREELANCER', payer: 'GPAYER' }); + seedEvent(db, { invoice_id: 1, event_type: 'InvoiceFunded', ledger: 100, timestamp: 1000 }); + seedEvent(db, { invoice_id: 1, event_type: 'InvoicePaid', ledger: 101, timestamp: 1001 }); + + const res = await request(app).get('/events?address=GFREELANCER&types=InvoicePaid'); + expect(res.status).toBe(200); + expect(res.body.events).toHaveLength(1); + expect(res.body.events[0].type).toBe('InvoicePaid'); + }); + + it('should support pagination and sort newest first', async () => { + seedInvoice(db, { id: 1, freelancer: 'GFREELANCER' }); + seedEvent(db, { invoice_id: 1, event_type: 'InvoiceFunded', ledger: 100, timestamp: 1000 }); + seedEvent(db, { invoice_id: 1, event_type: 'InvoicePaid', ledger: 101, timestamp: 1001 }); + + const res = await request(app).get('/events?address=GFREELANCER&page=1&pageSize=1'); + expect(res.status).toBe(200); + expect(res.body.events).toHaveLength(1); + expect(res.body.events[0].type).toBe('InvoicePaid'); // timestamp 1001 is newer + }); +}); diff --git a/indexer/tests/invoices.test.ts b/indexer/tests/invoices.test.ts index d8f717ac..806bc42e 100644 --- a/indexer/tests/invoices.test.ts +++ b/indexer/tests/invoices.test.ts @@ -169,3 +169,53 @@ describe('GET /invoices/:id', () => { expect(res.body.createdAt).toBe(1700000000); }); }); + +describe('GET /invoices', () => { + let db: ReturnType; + let app: ReturnType; + + beforeEach(() => { + db = createTestDb(); + app = createTestApp(db); + }); + + afterEach(() => { + db.close(); + }); + + it('should return all invoices when no query parameters are provided', async () => { + seedInvoice(db, { id: 1, token: 'USDC', status: 'Pending', freelancer: 'G1' }); + seedInvoice(db, { id: 2, token: 'USDC', status: 'Funded', freelancer: 'G2' }); + + const res = await request(app).get('/invoices'); + expect(res.status).toBe(200); + expect(res.headers['cache-control']).toBe('max-age=10'); + expect(res.body.invoices).toHaveLength(2); + expect(res.body.total).toBe(2); + }); + + it('should filter by state, token, and submitter', async () => { + seedInvoice(db, { id: 1, token: 'USDC', status: 'Pending', freelancer: 'G1' }); + seedInvoice(db, { id: 2, token: 'XLM', status: 'Funded', freelancer: 'G1' }); + seedInvoice(db, { id: 3, token: 'USDC', status: 'Pending', freelancer: 'G2' }); + + const res = await request(app).get('/invoices?state=Pending&token=USDC&submitter=G1'); + expect(res.status).toBe(200); + expect(res.body.invoices).toHaveLength(1); + expect(res.body.invoices[0].id).toBe(1); + expect(res.body.total).toBe(1); + }); + + it('should support pagination', async () => { + seedInvoice(db, { id: 1 }); + seedInvoice(db, { id: 2 }); + seedInvoice(db, { id: 3 }); + + const res = await request(app).get('/invoices?page=2&pageSize=2&sortBy=createdAt&sortOrder=asc'); + expect(res.status).toBe(200); + expect(res.body.invoices).toHaveLength(1); + expect(res.body.total).toBe(3); + expect(res.body.page).toBe(2); + expect(res.body.pageSize).toBe(2); + }); +}); diff --git a/sdk/coverage/clover.xml b/sdk/coverage/clover.xml new file mode 100644 index 00000000..520d75dc --- /dev/null +++ b/sdk/coverage/clover.xml @@ -0,0 +1,480 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/coverage/coverage-final.json b/sdk/coverage/coverage-final.json new file mode 100644 index 00000000..2664543c --- /dev/null +++ b/sdk/coverage/coverage-final.json @@ -0,0 +1,35 @@ +{"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/client.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/client.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/client.test.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/client.test.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/client.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/client.ts","statementMap":{"0":{"start":{"line":31,"column":31},"end":{"line":31,"column":68}},"1":{"start":{"line":36,"column":31},"end":{"line":36,"column":60}},"2":{"start":{"line":93,"column":4},"end":{"line":93,"column":52}},"3":{"start":{"line":94,"column":4},"end":{"line":94,"column":54}},"4":{"start":{"line":95,"column":4},"end":{"line":95,"column":40}},"5":{"start":{"line":96,"column":4},"end":{"line":96,"column":32}},"6":{"start":{"line":118,"column":4},"end":{"line":128,"column":7}},"7":{"start":{"line":148,"column":4},"end":{"line":156,"column":7}},"8":{"start":{"line":168,"column":4},"end":{"line":168,"column":33}},"9":{"start":{"line":186,"column":4},"end":{"line":189,"column":5}},"10":{"start":{"line":187,"column":6},"end":{"line":188,"column":23}},"11":{"start":{"line":190,"column":4},"end":{"line":190,"column":91}},"12":{"start":{"line":203,"column":4},"end":{"line":206,"column":5}},"13":{"start":{"line":204,"column":6},"end":{"line":205,"column":26}},"14":{"start":{"line":207,"column":4},"end":{"line":207,"column":85}},"15":{"start":{"line":229,"column":10},"end":{"line":229,"column":43}},"16":{"start":{"line":232,"column":4},"end":{"line":232,"column":41}},"17":{"start":{"line":237,"column":4},"end":{"line":241,"column":5}},"18":{"start":{"line":238,"column":6},"end":{"line":240,"column":8}},"19":{"start":{"line":242,"column":4},"end":{"line":242,"column":24}},"20":{"start":{"line":246,"column":4},"end":{"line":246,"column":46}},"21":{"start":{"line":250,"column":4},"end":{"line":250,"column":42}},"22":{"start":{"line":254,"column":19},"end":{"line":254,"column":37}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":92,"column":2},"end":{"line":92,"column":14}},"loc":{"start":{"line":92,"column":37},"end":{"line":97,"column":3}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":114,"column":2},"end":{"line":114,"column":8}},"loc":{"start":{"line":116,"column":54},"end":{"line":129,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":142,"column":2},"end":{"line":142,"column":8}},"loc":{"start":{"line":144,"column":54},"end":{"line":157,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":167,"column":2},"end":{"line":167,"column":8}},"loc":{"start":{"line":167,"column":39},"end":{"line":169,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":183,"column":2},"end":{"line":183,"column":7}},"loc":{"start":{"line":184,"column":19},"end":{"line":191,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":200,"column":2},"end":{"line":200,"column":7}},"loc":{"start":{"line":200,"column":24},"end":{"line":208,"column":3}}},"6":{"name":"(anonymous_6)","decl":{"start":{"line":228,"column":0},"end":{"line":228,"column":6}},"loc":{"start":{"line":228,"column":0},"end":{"line":252,"column":1}}},"7":{"name":"(anonymous_7)","decl":{"start":{"line":231,"column":2},"end":{"line":231,"column":11}},"loc":{"start":{"line":231,"column":35},"end":{"line":233,"column":3}}},"8":{"name":"(anonymous_8)","decl":{"start":{"line":236,"column":2},"end":{"line":236,"column":6}},"loc":{"start":{"line":236,"column":12},"end":{"line":243,"column":3}}},"9":{"name":"(anonymous_9)","decl":{"start":{"line":245,"column":2},"end":{"line":245,"column":7}},"loc":{"start":{"line":245,"column":37},"end":{"line":247,"column":3}}},"10":{"name":"(anonymous_10)","decl":{"start":{"line":249,"column":2},"end":{"line":249,"column":7}},"loc":{"start":{"line":249,"column":24},"end":{"line":251,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":119,"column":14},"end":{"line":119,"column":48}},"type":"binary-expr","locations":[{"start":{"line":119,"column":14},"end":{"line":119,"column":29}},{"start":{"line":119,"column":33},"end":{"line":119,"column":48}}]},"1":{"loc":{"start":{"line":122,"column":8},"end":{"line":126,"column":66}},"type":"binary-expr","locations":[{"start":{"line":122,"column":8},"end":{"line":122,"column":27}},{"start":{"line":126,"column":8},"end":{"line":126,"column":66}}]},"2":{"loc":{"start":{"line":149,"column":14},"end":{"line":149,"column":48}},"type":"binary-expr","locations":[{"start":{"line":149,"column":14},"end":{"line":149,"column":29}},{"start":{"line":149,"column":33},"end":{"line":149,"column":48}}]},"3":{"loc":{"start":{"line":152,"column":8},"end":{"line":154,"column":10}},"type":"binary-expr","locations":[{"start":{"line":152,"column":8},"end":{"line":152,"column":27}},{"start":{"line":154,"column":8},"end":{"line":154,"column":10}}]},"4":{"loc":{"start":{"line":186,"column":4},"end":{"line":189,"column":5}},"type":"if","locations":[{"start":{"line":186,"column":4},"end":{"line":189,"column":5}}]},"5":{"loc":{"start":{"line":203,"column":4},"end":{"line":206,"column":5}},"type":"if","locations":[{"start":{"line":203,"column":4},"end":{"line":206,"column":5}}]},"6":{"loc":{"start":{"line":237,"column":4},"end":{"line":241,"column":5}},"type":"if","locations":[{"start":{"line":237,"column":4},"end":{"line":241,"column":5}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0],"5":[0],"6":[0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/errors.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/errors.ts","statementMap":{"0":{"start":{"line":3,"column":4},"end":{"line":3,"column":19}},"1":{"start":{"line":2,"column":47},"end":{"line":2,"column":60}},"2":{"start":{"line":4,"column":4},"end":{"line":4,"column":38}},"3":{"start":{"line":49,"column":24},"end":{"line":49,"column":37}},"4":{"start":{"line":50,"column":18},"end":{"line":50,"column":63}},"5":{"start":{"line":51,"column":4},"end":{"line":92,"column":5}},"6":{"start":{"line":52,"column":19},"end":{"line":52,"column":41}},"7":{"start":{"line":53,"column":6},"end":{"line":91,"column":7}},"8":{"start":{"line":54,"column":16},"end":{"line":54,"column":54}},"9":{"start":{"line":55,"column":16},"end":{"line":55,"column":52}},"10":{"start":{"line":56,"column":16},"end":{"line":56,"column":50}},"11":{"start":{"line":57,"column":16},"end":{"line":57,"column":48}},"12":{"start":{"line":58,"column":16},"end":{"line":58,"column":51}},"13":{"start":{"line":59,"column":16},"end":{"line":59,"column":52}},"14":{"start":{"line":60,"column":16},"end":{"line":60,"column":58}},"15":{"start":{"line":61,"column":16},"end":{"line":61,"column":53}},"16":{"start":{"line":62,"column":16},"end":{"line":62,"column":55}},"17":{"start":{"line":63,"column":17},"end":{"line":63,"column":54}},"18":{"start":{"line":64,"column":17},"end":{"line":64,"column":55}},"19":{"start":{"line":65,"column":17},"end":{"line":65,"column":59}},"20":{"start":{"line":66,"column":17},"end":{"line":66,"column":54}},"21":{"start":{"line":67,"column":17},"end":{"line":67,"column":53}},"22":{"start":{"line":68,"column":17},"end":{"line":68,"column":56}},"23":{"start":{"line":69,"column":17},"end":{"line":69,"column":58}},"24":{"start":{"line":70,"column":17},"end":{"line":70,"column":55}},"25":{"start":{"line":71,"column":17},"end":{"line":71,"column":58}},"26":{"start":{"line":72,"column":17},"end":{"line":72,"column":52}},"27":{"start":{"line":73,"column":17},"end":{"line":73,"column":54}},"28":{"start":{"line":74,"column":17},"end":{"line":74,"column":57}},"29":{"start":{"line":75,"column":17},"end":{"line":75,"column":55}},"30":{"start":{"line":76,"column":17},"end":{"line":76,"column":55}},"31":{"start":{"line":77,"column":17},"end":{"line":77,"column":51}},"32":{"start":{"line":78,"column":17},"end":{"line":78,"column":55}},"33":{"start":{"line":79,"column":17},"end":{"line":79,"column":54}},"34":{"start":{"line":80,"column":17},"end":{"line":80,"column":54}},"35":{"start":{"line":81,"column":17},"end":{"line":81,"column":53}},"36":{"start":{"line":82,"column":17},"end":{"line":82,"column":51}},"37":{"start":{"line":83,"column":17},"end":{"line":83,"column":59}},"38":{"start":{"line":84,"column":17},"end":{"line":84,"column":61}},"39":{"start":{"line":85,"column":17},"end":{"line":85,"column":58}},"40":{"start":{"line":86,"column":17},"end":{"line":86,"column":58}},"41":{"start":{"line":87,"column":17},"end":{"line":87,"column":55}},"42":{"start":{"line":88,"column":17},"end":{"line":88,"column":55}},"43":{"start":{"line":89,"column":17},"end":{"line":89,"column":54}},"44":{"start":{"line":90,"column":17},"end":{"line":90,"column":61}},"45":{"start":{"line":93,"column":4},"end":{"line":93,"column":34}},"46":{"start":{"line":7,"column":9},"end":{"line":7,"column":112}},"47":{"start":{"line":7,"column":93},"end":{"line":7,"column":107}},"48":{"start":{"line":8,"column":9},"end":{"line":8,"column":115}},"49":{"start":{"line":8,"column":96},"end":{"line":8,"column":110}},"50":{"start":{"line":9,"column":9},"end":{"line":9,"column":111}},"51":{"start":{"line":9,"column":92},"end":{"line":9,"column":106}},"52":{"start":{"line":10,"column":9},"end":{"line":10,"column":107}},"53":{"start":{"line":10,"column":88},"end":{"line":10,"column":102}},"54":{"start":{"line":11,"column":9},"end":{"line":11,"column":104}},"55":{"start":{"line":11,"column":85},"end":{"line":11,"column":99}},"56":{"start":{"line":12,"column":9},"end":{"line":12,"column":107}},"57":{"start":{"line":12,"column":88},"end":{"line":12,"column":102}},"58":{"start":{"line":13,"column":9},"end":{"line":13,"column":120}},"59":{"start":{"line":13,"column":101},"end":{"line":13,"column":115}},"60":{"start":{"line":14,"column":9},"end":{"line":14,"column":110}},"61":{"start":{"line":14,"column":91},"end":{"line":14,"column":105}},"62":{"start":{"line":15,"column":9},"end":{"line":15,"column":113}},"63":{"start":{"line":15,"column":94},"end":{"line":15,"column":108}},"64":{"start":{"line":16,"column":9},"end":{"line":16,"column":111}},"65":{"start":{"line":16,"column":91},"end":{"line":16,"column":106}},"66":{"start":{"line":17,"column":9},"end":{"line":17,"column":113}},"67":{"start":{"line":17,"column":93},"end":{"line":17,"column":108}},"68":{"start":{"line":18,"column":9},"end":{"line":18,"column":120}},"69":{"start":{"line":18,"column":100},"end":{"line":18,"column":115}},"70":{"start":{"line":19,"column":9},"end":{"line":19,"column":110}},"71":{"start":{"line":19,"column":90},"end":{"line":19,"column":105}},"72":{"start":{"line":20,"column":9},"end":{"line":20,"column":109}},"73":{"start":{"line":20,"column":89},"end":{"line":20,"column":104}},"74":{"start":{"line":21,"column":9},"end":{"line":21,"column":114}},"75":{"start":{"line":21,"column":94},"end":{"line":21,"column":109}},"76":{"start":{"line":22,"column":9},"end":{"line":22,"column":118}},"77":{"start":{"line":22,"column":98},"end":{"line":22,"column":113}},"78":{"start":{"line":23,"column":9},"end":{"line":23,"column":112}},"79":{"start":{"line":23,"column":92},"end":{"line":23,"column":107}},"80":{"start":{"line":24,"column":9},"end":{"line":24,"column":119}},"81":{"start":{"line":24,"column":99},"end":{"line":24,"column":114}},"82":{"start":{"line":25,"column":9},"end":{"line":25,"column":106}},"83":{"start":{"line":25,"column":86},"end":{"line":25,"column":101}},"84":{"start":{"line":26,"column":9},"end":{"line":26,"column":111}},"85":{"start":{"line":26,"column":91},"end":{"line":26,"column":106}},"86":{"start":{"line":27,"column":9},"end":{"line":27,"column":117}},"87":{"start":{"line":27,"column":97},"end":{"line":27,"column":112}},"88":{"start":{"line":28,"column":9},"end":{"line":28,"column":112}},"89":{"start":{"line":28,"column":92},"end":{"line":28,"column":107}},"90":{"start":{"line":29,"column":9},"end":{"line":29,"column":112}},"91":{"start":{"line":29,"column":92},"end":{"line":29,"column":107}},"92":{"start":{"line":30,"column":9},"end":{"line":30,"column":104}},"93":{"start":{"line":30,"column":84},"end":{"line":30,"column":99}},"94":{"start":{"line":31,"column":9},"end":{"line":31,"column":112}},"95":{"start":{"line":31,"column":92},"end":{"line":31,"column":107}},"96":{"start":{"line":32,"column":9},"end":{"line":32,"column":110}},"97":{"start":{"line":32,"column":90},"end":{"line":32,"column":105}},"98":{"start":{"line":33,"column":9},"end":{"line":33,"column":112}},"99":{"start":{"line":33,"column":92},"end":{"line":33,"column":107}},"100":{"start":{"line":34,"column":9},"end":{"line":34,"column":110}},"101":{"start":{"line":34,"column":90},"end":{"line":34,"column":105}},"102":{"start":{"line":35,"column":9},"end":{"line":35,"column":104}},"103":{"start":{"line":35,"column":84},"end":{"line":35,"column":99}},"104":{"start":{"line":36,"column":9},"end":{"line":36,"column":120}},"105":{"start":{"line":36,"column":100},"end":{"line":36,"column":115}},"106":{"start":{"line":37,"column":9},"end":{"line":37,"column":126}},"107":{"start":{"line":37,"column":106},"end":{"line":37,"column":121}},"108":{"start":{"line":38,"column":9},"end":{"line":38,"column":118}},"109":{"start":{"line":38,"column":98},"end":{"line":38,"column":113}},"110":{"start":{"line":39,"column":9},"end":{"line":39,"column":120}},"111":{"start":{"line":39,"column":100},"end":{"line":39,"column":115}},"112":{"start":{"line":40,"column":9},"end":{"line":40,"column":112}},"113":{"start":{"line":40,"column":92},"end":{"line":40,"column":107}},"114":{"start":{"line":41,"column":9},"end":{"line":41,"column":113}},"115":{"start":{"line":41,"column":93},"end":{"line":41,"column":108}},"116":{"start":{"line":42,"column":9},"end":{"line":42,"column":111}},"117":{"start":{"line":42,"column":91},"end":{"line":42,"column":106}},"118":{"start":{"line":43,"column":9},"end":{"line":43,"column":125}},"119":{"start":{"line":43,"column":105},"end":{"line":43,"column":120}},"120":{"start":{"line":44,"column":9},"end":{"line":44,"column":110}},"121":{"start":{"line":44,"column":90},"end":{"line":44,"column":105}},"122":{"start":{"line":45,"column":9},"end":{"line":45,"column":112}},"123":{"start":{"line":45,"column":92},"end":{"line":45,"column":107}},"124":{"start":{"line":46,"column":9},"end":{"line":46,"column":119}},"125":{"start":{"line":46,"column":98},"end":{"line":46,"column":114}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":2,"column":2},"end":{"line":2,"column":14}},"loc":{"start":{"line":2,"column":60},"end":{"line":5,"column":3}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":48,"column":2},"end":{"line":48,"column":8}},"loc":{"start":{"line":48,"column":29},"end":{"line":94,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":7,"column":52},"end":{"line":7,"column":64}},"loc":{"start":{"line":7,"column":89},"end":{"line":7,"column":109}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":8,"column":50},"end":{"line":8,"column":62}},"loc":{"start":{"line":8,"column":92},"end":{"line":8,"column":112}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":9,"column":48},"end":{"line":9,"column":60}},"loc":{"start":{"line":9,"column":88},"end":{"line":9,"column":108}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":10,"column":46},"end":{"line":10,"column":58}},"loc":{"start":{"line":10,"column":84},"end":{"line":10,"column":104}}},"6":{"name":"(anonymous_6)","decl":{"start":{"line":11,"column":49},"end":{"line":11,"column":61}},"loc":{"start":{"line":11,"column":81},"end":{"line":11,"column":101}}},"7":{"name":"(anonymous_7)","decl":{"start":{"line":12,"column":50},"end":{"line":12,"column":62}},"loc":{"start":{"line":12,"column":84},"end":{"line":12,"column":104}}},"8":{"name":"(anonymous_8)","decl":{"start":{"line":13,"column":56},"end":{"line":13,"column":68}},"loc":{"start":{"line":13,"column":97},"end":{"line":13,"column":117}}},"9":{"name":"(anonymous_9)","decl":{"start":{"line":14,"column":51},"end":{"line":14,"column":63}},"loc":{"start":{"line":14,"column":87},"end":{"line":14,"column":107}}},"10":{"name":"(anonymous_10)","decl":{"start":{"line":15,"column":53},"end":{"line":15,"column":65}},"loc":{"start":{"line":15,"column":90},"end":{"line":15,"column":110}}},"11":{"name":"(anonymous_11)","decl":{"start":{"line":16,"column":51},"end":{"line":16,"column":63}},"loc":{"start":{"line":16,"column":87},"end":{"line":16,"column":108}}},"12":{"name":"(anonymous_12)","decl":{"start":{"line":17,"column":52},"end":{"line":17,"column":64}},"loc":{"start":{"line":17,"column":89},"end":{"line":17,"column":110}}},"13":{"name":"(anonymous_13)","decl":{"start":{"line":18,"column":56},"end":{"line":18,"column":68}},"loc":{"start":{"line":18,"column":96},"end":{"line":18,"column":117}}},"14":{"name":"(anonymous_14)","decl":{"start":{"line":19,"column":51},"end":{"line":19,"column":63}},"loc":{"start":{"line":19,"column":86},"end":{"line":19,"column":107}}},"15":{"name":"(anonymous_15)","decl":{"start":{"line":20,"column":50},"end":{"line":20,"column":62}},"loc":{"start":{"line":20,"column":85},"end":{"line":20,"column":106}}},"16":{"name":"(anonymous_16)","decl":{"start":{"line":21,"column":53},"end":{"line":21,"column":65}},"loc":{"start":{"line":21,"column":90},"end":{"line":21,"column":111}}},"17":{"name":"(anonymous_17)","decl":{"start":{"line":22,"column":55},"end":{"line":22,"column":67}},"loc":{"start":{"line":22,"column":94},"end":{"line":22,"column":115}}},"18":{"name":"(anonymous_18)","decl":{"start":{"line":23,"column":52},"end":{"line":23,"column":64}},"loc":{"start":{"line":23,"column":88},"end":{"line":23,"column":109}}},"19":{"name":"(anonymous_19)","decl":{"start":{"line":24,"column":55},"end":{"line":24,"column":67}},"loc":{"start":{"line":24,"column":95},"end":{"line":24,"column":116}}},"20":{"name":"(anonymous_20)","decl":{"start":{"line":25,"column":49},"end":{"line":25,"column":61}},"loc":{"start":{"line":25,"column":82},"end":{"line":25,"column":103}}},"21":{"name":"(anonymous_21)","decl":{"start":{"line":26,"column":51},"end":{"line":26,"column":63}},"loc":{"start":{"line":26,"column":87},"end":{"line":26,"column":108}}},"22":{"name":"(anonymous_22)","decl":{"start":{"line":27,"column":54},"end":{"line":27,"column":66}},"loc":{"start":{"line":27,"column":93},"end":{"line":27,"column":114}}},"23":{"name":"(anonymous_23)","decl":{"start":{"line":28,"column":52},"end":{"line":28,"column":64}},"loc":{"start":{"line":28,"column":88},"end":{"line":28,"column":109}}},"24":{"name":"(anonymous_24)","decl":{"start":{"line":29,"column":52},"end":{"line":29,"column":64}},"loc":{"start":{"line":29,"column":88},"end":{"line":29,"column":109}}},"25":{"name":"(anonymous_25)","decl":{"start":{"line":30,"column":48},"end":{"line":30,"column":60}},"loc":{"start":{"line":30,"column":80},"end":{"line":30,"column":101}}},"26":{"name":"(anonymous_26)","decl":{"start":{"line":31,"column":52},"end":{"line":31,"column":64}},"loc":{"start":{"line":31,"column":88},"end":{"line":31,"column":109}}},"27":{"name":"(anonymous_27)","decl":{"start":{"line":32,"column":51},"end":{"line":32,"column":63}},"loc":{"start":{"line":32,"column":86},"end":{"line":32,"column":107}}},"28":{"name":"(anonymous_28)","decl":{"start":{"line":33,"column":51},"end":{"line":33,"column":63}},"loc":{"start":{"line":33,"column":88},"end":{"line":33,"column":109}}},"29":{"name":"(anonymous_29)","decl":{"start":{"line":34,"column":50},"end":{"line":34,"column":62}},"loc":{"start":{"line":34,"column":86},"end":{"line":34,"column":107}}},"30":{"name":"(anonymous_30)","decl":{"start":{"line":35,"column":48},"end":{"line":35,"column":60}},"loc":{"start":{"line":35,"column":80},"end":{"line":35,"column":101}}},"31":{"name":"(anonymous_31)","decl":{"start":{"line":36,"column":56},"end":{"line":36,"column":68}},"loc":{"start":{"line":36,"column":96},"end":{"line":36,"column":117}}},"32":{"name":"(anonymous_32)","decl":{"start":{"line":37,"column":58},"end":{"line":37,"column":70}},"loc":{"start":{"line":37,"column":102},"end":{"line":37,"column":123}}},"33":{"name":"(anonymous_33)","decl":{"start":{"line":38,"column":55},"end":{"line":38,"column":67}},"loc":{"start":{"line":38,"column":94},"end":{"line":38,"column":115}}},"34":{"name":"(anonymous_34)","decl":{"start":{"line":39,"column":55},"end":{"line":39,"column":67}},"loc":{"start":{"line":39,"column":96},"end":{"line":39,"column":117}}},"35":{"name":"(anonymous_35)","decl":{"start":{"line":40,"column":52},"end":{"line":40,"column":64}},"loc":{"start":{"line":40,"column":88},"end":{"line":40,"column":109}}},"36":{"name":"(anonymous_36)","decl":{"start":{"line":41,"column":52},"end":{"line":41,"column":64}},"loc":{"start":{"line":41,"column":89},"end":{"line":41,"column":110}}},"37":{"name":"(anonymous_37)","decl":{"start":{"line":42,"column":51},"end":{"line":42,"column":63}},"loc":{"start":{"line":42,"column":87},"end":{"line":42,"column":108}}},"38":{"name":"(anonymous_38)","decl":{"start":{"line":43,"column":58},"end":{"line":43,"column":70}},"loc":{"start":{"line":43,"column":101},"end":{"line":43,"column":122}}},"39":{"name":"(anonymous_39)","decl":{"start":{"line":44,"column":51},"end":{"line":44,"column":63}},"loc":{"start":{"line":44,"column":86},"end":{"line":44,"column":107}}},"40":{"name":"(anonymous_40)","decl":{"start":{"line":45,"column":52},"end":{"line":45,"column":64}},"loc":{"start":{"line":45,"column":88},"end":{"line":45,"column":109}}},"41":{"name":"(anonymous_41)","decl":{"start":{"line":46,"column":55},"end":{"line":46,"column":67}},"loc":{"start":{"line":46,"column":94},"end":{"line":46,"column":116}}}},"branchMap":{"0":{"loc":{"start":{"line":51,"column":4},"end":{"line":92,"column":5}},"type":"if","locations":[{"start":{"line":51,"column":4},"end":{"line":92,"column":5}}]},"1":{"loc":{"start":{"line":53,"column":6},"end":{"line":91,"column":7}},"type":"switch","locations":[{"start":{"line":54,"column":8},"end":{"line":54,"column":54}},{"start":{"line":55,"column":8},"end":{"line":55,"column":52}},{"start":{"line":56,"column":8},"end":{"line":56,"column":50}},{"start":{"line":57,"column":8},"end":{"line":57,"column":48}},{"start":{"line":58,"column":8},"end":{"line":58,"column":51}},{"start":{"line":59,"column":8},"end":{"line":59,"column":52}},{"start":{"line":60,"column":8},"end":{"line":60,"column":58}},{"start":{"line":61,"column":8},"end":{"line":61,"column":53}},{"start":{"line":62,"column":8},"end":{"line":62,"column":55}},{"start":{"line":63,"column":8},"end":{"line":63,"column":54}},{"start":{"line":64,"column":8},"end":{"line":64,"column":55}},{"start":{"line":65,"column":8},"end":{"line":65,"column":59}},{"start":{"line":66,"column":8},"end":{"line":66,"column":54}},{"start":{"line":67,"column":8},"end":{"line":67,"column":53}},{"start":{"line":68,"column":8},"end":{"line":68,"column":56}},{"start":{"line":69,"column":8},"end":{"line":69,"column":58}},{"start":{"line":70,"column":8},"end":{"line":70,"column":55}},{"start":{"line":71,"column":8},"end":{"line":71,"column":58}},{"start":{"line":72,"column":8},"end":{"line":72,"column":52}},{"start":{"line":73,"column":8},"end":{"line":73,"column":54}},{"start":{"line":74,"column":8},"end":{"line":74,"column":57}},{"start":{"line":75,"column":8},"end":{"line":75,"column":55}},{"start":{"line":76,"column":8},"end":{"line":76,"column":55}},{"start":{"line":77,"column":8},"end":{"line":77,"column":51}},{"start":{"line":78,"column":8},"end":{"line":78,"column":55}},{"start":{"line":79,"column":8},"end":{"line":79,"column":54}},{"start":{"line":80,"column":8},"end":{"line":80,"column":54}},{"start":{"line":81,"column":8},"end":{"line":81,"column":53}},{"start":{"line":82,"column":8},"end":{"line":82,"column":51}},{"start":{"line":83,"column":8},"end":{"line":83,"column":59}},{"start":{"line":84,"column":8},"end":{"line":84,"column":61}},{"start":{"line":85,"column":8},"end":{"line":85,"column":58}},{"start":{"line":86,"column":8},"end":{"line":86,"column":58}},{"start":{"line":87,"column":8},"end":{"line":87,"column":55}},{"start":{"line":88,"column":8},"end":{"line":88,"column":55}},{"start":{"line":89,"column":8},"end":{"line":89,"column":54}},{"start":{"line":90,"column":8},"end":{"line":90,"column":61}}]},"2":{"loc":{"start":{"line":7,"column":64},"end":{"line":7,"column":89}},"type":"default-arg","locations":[{"start":{"line":7,"column":70},"end":{"line":7,"column":89}}]},"3":{"loc":{"start":{"line":8,"column":62},"end":{"line":8,"column":92}},"type":"default-arg","locations":[{"start":{"line":8,"column":68},"end":{"line":8,"column":92}}]},"4":{"loc":{"start":{"line":9,"column":60},"end":{"line":9,"column":88}},"type":"default-arg","locations":[{"start":{"line":9,"column":66},"end":{"line":9,"column":88}}]},"5":{"loc":{"start":{"line":10,"column":58},"end":{"line":10,"column":84}},"type":"default-arg","locations":[{"start":{"line":10,"column":64},"end":{"line":10,"column":84}}]},"6":{"loc":{"start":{"line":11,"column":61},"end":{"line":11,"column":81}},"type":"default-arg","locations":[{"start":{"line":11,"column":67},"end":{"line":11,"column":81}}]},"7":{"loc":{"start":{"line":12,"column":62},"end":{"line":12,"column":84}},"type":"default-arg","locations":[{"start":{"line":12,"column":68},"end":{"line":12,"column":84}}]},"8":{"loc":{"start":{"line":13,"column":68},"end":{"line":13,"column":97}},"type":"default-arg","locations":[{"start":{"line":13,"column":74},"end":{"line":13,"column":97}}]},"9":{"loc":{"start":{"line":14,"column":63},"end":{"line":14,"column":87}},"type":"default-arg","locations":[{"start":{"line":14,"column":69},"end":{"line":14,"column":87}}]},"10":{"loc":{"start":{"line":15,"column":65},"end":{"line":15,"column":90}},"type":"default-arg","locations":[{"start":{"line":15,"column":71},"end":{"line":15,"column":90}}]},"11":{"loc":{"start":{"line":16,"column":63},"end":{"line":16,"column":87}},"type":"default-arg","locations":[{"start":{"line":16,"column":69},"end":{"line":16,"column":87}}]},"12":{"loc":{"start":{"line":17,"column":64},"end":{"line":17,"column":89}},"type":"default-arg","locations":[{"start":{"line":17,"column":70},"end":{"line":17,"column":89}}]},"13":{"loc":{"start":{"line":18,"column":68},"end":{"line":18,"column":96}},"type":"default-arg","locations":[{"start":{"line":18,"column":74},"end":{"line":18,"column":96}}]},"14":{"loc":{"start":{"line":19,"column":63},"end":{"line":19,"column":86}},"type":"default-arg","locations":[{"start":{"line":19,"column":69},"end":{"line":19,"column":86}}]},"15":{"loc":{"start":{"line":20,"column":62},"end":{"line":20,"column":85}},"type":"default-arg","locations":[{"start":{"line":20,"column":68},"end":{"line":20,"column":85}}]},"16":{"loc":{"start":{"line":21,"column":65},"end":{"line":21,"column":90}},"type":"default-arg","locations":[{"start":{"line":21,"column":71},"end":{"line":21,"column":90}}]},"17":{"loc":{"start":{"line":22,"column":67},"end":{"line":22,"column":94}},"type":"default-arg","locations":[{"start":{"line":22,"column":73},"end":{"line":22,"column":94}}]},"18":{"loc":{"start":{"line":23,"column":64},"end":{"line":23,"column":88}},"type":"default-arg","locations":[{"start":{"line":23,"column":70},"end":{"line":23,"column":88}}]},"19":{"loc":{"start":{"line":24,"column":67},"end":{"line":24,"column":95}},"type":"default-arg","locations":[{"start":{"line":24,"column":73},"end":{"line":24,"column":95}}]},"20":{"loc":{"start":{"line":25,"column":61},"end":{"line":25,"column":82}},"type":"default-arg","locations":[{"start":{"line":25,"column":67},"end":{"line":25,"column":82}}]},"21":{"loc":{"start":{"line":26,"column":63},"end":{"line":26,"column":87}},"type":"default-arg","locations":[{"start":{"line":26,"column":69},"end":{"line":26,"column":87}}]},"22":{"loc":{"start":{"line":27,"column":66},"end":{"line":27,"column":93}},"type":"default-arg","locations":[{"start":{"line":27,"column":72},"end":{"line":27,"column":93}}]},"23":{"loc":{"start":{"line":28,"column":64},"end":{"line":28,"column":88}},"type":"default-arg","locations":[{"start":{"line":28,"column":70},"end":{"line":28,"column":88}}]},"24":{"loc":{"start":{"line":29,"column":64},"end":{"line":29,"column":88}},"type":"default-arg","locations":[{"start":{"line":29,"column":70},"end":{"line":29,"column":88}}]},"25":{"loc":{"start":{"line":30,"column":60},"end":{"line":30,"column":80}},"type":"default-arg","locations":[{"start":{"line":30,"column":66},"end":{"line":30,"column":80}}]},"26":{"loc":{"start":{"line":31,"column":64},"end":{"line":31,"column":88}},"type":"default-arg","locations":[{"start":{"line":31,"column":70},"end":{"line":31,"column":88}}]},"27":{"loc":{"start":{"line":32,"column":63},"end":{"line":32,"column":86}},"type":"default-arg","locations":[{"start":{"line":32,"column":69},"end":{"line":32,"column":86}}]},"28":{"loc":{"start":{"line":33,"column":63},"end":{"line":33,"column":88}},"type":"default-arg","locations":[{"start":{"line":33,"column":69},"end":{"line":33,"column":88}}]},"29":{"loc":{"start":{"line":34,"column":62},"end":{"line":34,"column":86}},"type":"default-arg","locations":[{"start":{"line":34,"column":68},"end":{"line":34,"column":86}}]},"30":{"loc":{"start":{"line":35,"column":60},"end":{"line":35,"column":80}},"type":"default-arg","locations":[{"start":{"line":35,"column":66},"end":{"line":35,"column":80}}]},"31":{"loc":{"start":{"line":36,"column":68},"end":{"line":36,"column":96}},"type":"default-arg","locations":[{"start":{"line":36,"column":74},"end":{"line":36,"column":96}}]},"32":{"loc":{"start":{"line":37,"column":70},"end":{"line":37,"column":102}},"type":"default-arg","locations":[{"start":{"line":37,"column":76},"end":{"line":37,"column":102}}]},"33":{"loc":{"start":{"line":38,"column":67},"end":{"line":38,"column":94}},"type":"default-arg","locations":[{"start":{"line":38,"column":73},"end":{"line":38,"column":94}}]},"34":{"loc":{"start":{"line":39,"column":67},"end":{"line":39,"column":96}},"type":"default-arg","locations":[{"start":{"line":39,"column":73},"end":{"line":39,"column":96}}]},"35":{"loc":{"start":{"line":40,"column":64},"end":{"line":40,"column":88}},"type":"default-arg","locations":[{"start":{"line":40,"column":70},"end":{"line":40,"column":88}}]},"36":{"loc":{"start":{"line":41,"column":64},"end":{"line":41,"column":89}},"type":"default-arg","locations":[{"start":{"line":41,"column":70},"end":{"line":41,"column":89}}]},"37":{"loc":{"start":{"line":42,"column":63},"end":{"line":42,"column":87}},"type":"default-arg","locations":[{"start":{"line":42,"column":69},"end":{"line":42,"column":87}}]},"38":{"loc":{"start":{"line":43,"column":70},"end":{"line":43,"column":101}},"type":"default-arg","locations":[{"start":{"line":43,"column":76},"end":{"line":43,"column":101}}]},"39":{"loc":{"start":{"line":44,"column":63},"end":{"line":44,"column":86}},"type":"default-arg","locations":[{"start":{"line":44,"column":69},"end":{"line":44,"column":86}}]},"40":{"loc":{"start":{"line":45,"column":64},"end":{"line":45,"column":88}},"type":"default-arg","locations":[{"start":{"line":45,"column":70},"end":{"line":45,"column":88}}]},"41":{"loc":{"start":{"line":46,"column":67},"end":{"line":46,"column":94}},"type":"default-arg","locations":[{"start":{"line":46,"column":73},"end":{"line":46,"column":94}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0},"b":{"0":[0],"1":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"2":[0],"3":[0],"4":[0],"5":[0],"6":[0],"7":[0],"8":[0],"9":[0],"10":[0],"11":[0],"12":[0],"13":[0],"14":[0],"15":[0],"16":[0],"17":[0],"18":[0],"19":[0],"20":[0],"21":[0],"22":[0],"23":[0],"24":[0],"25":[0],"26":[0],"27":[0],"28":[0],"29":[0],"30":[0],"31":[0],"32":[0],"33":[0],"34":[0],"35":[0],"36":[0],"37":[0],"38":[0],"39":[0],"40":[0],"41":[0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/index.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/index.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/events/subscribe.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/events/subscribe.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/events/types.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/events/types.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/cancelInvoice.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/cancelInvoice.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/fundInvoice.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/fundInvoice.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/governance.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/governance.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/markPaid.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/markPaid.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/queries.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/queries.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/queries.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/queries.ts","statementMap":{"0":{"start":{"line":37,"column":19},"end":{"line":37,"column":48}},"1":{"start":{"line":38,"column":13},"end":{"line":40,"column":null}},"2":{"start":{"line":43,"column":13},"end":{"line":49,"column":12}},"3":{"start":{"line":51,"column":14},"end":{"line":51,"column":50}},"4":{"start":{"line":53,"column":2},"end":{"line":58,"column":3}},"5":{"start":{"line":54,"column":4},"end":{"line":56,"column":5}},"6":{"start":{"line":55,"column":6},"end":{"line":55,"column":75}},"7":{"start":{"line":57,"column":4},"end":{"line":57,"column":40}},"8":{"start":{"line":59,"column":2},"end":{"line":61,"column":3}},"9":{"start":{"line":60,"column":4},"end":{"line":60,"column":73}},"10":{"start":{"line":63,"column":14},"end":{"line":63,"column":73}},"11":{"start":{"line":64,"column":18},"end":{"line":64,"column":41}},"12":{"start":{"line":65,"column":23},"end":{"line":65,"column":51}},"13":{"start":{"line":67,"column":2},"end":{"line":83,"column":4}},"14":{"start":{"line":111,"column":19},"end":{"line":111,"column":48}},"15":{"start":{"line":112,"column":13},"end":{"line":116,"column":null}},"16":{"start":{"line":119,"column":13},"end":{"line":125,"column":12}},"17":{"start":{"line":127,"column":14},"end":{"line":127,"column":50}},"18":{"start":{"line":129,"column":2},"end":{"line":131,"column":3}},"19":{"start":{"line":130,"column":4},"end":{"line":130,"column":40}},"20":{"start":{"line":132,"column":2},"end":{"line":134,"column":3}},"21":{"start":{"line":133,"column":4},"end":{"line":133,"column":14}},"22":{"start":{"line":136,"column":17},"end":{"line":136,"column":78}},"23":{"start":{"line":137,"column":2},"end":{"line":157,"column":5}},"24":{"start":{"line":138,"column":20},"end":{"line":138,"column":43}},"25":{"start":{"line":139,"column":25},"end":{"line":139,"column":53}},"26":{"start":{"line":140,"column":4},"end":{"line":156,"column":6}},"27":{"start":{"line":185,"column":19},"end":{"line":185,"column":48}},"28":{"start":{"line":186,"column":13},"end":{"line":190,"column":null}},"29":{"start":{"line":193,"column":13},"end":{"line":199,"column":12}},"30":{"start":{"line":201,"column":14},"end":{"line":201,"column":50}},"31":{"start":{"line":203,"column":2},"end":{"line":205,"column":3}},"32":{"start":{"line":204,"column":4},"end":{"line":204,"column":40}},"33":{"start":{"line":206,"column":2},"end":{"line":208,"column":3}},"34":{"start":{"line":207,"column":4},"end":{"line":207,"column":14}},"35":{"start":{"line":210,"column":17},"end":{"line":210,"column":78}},"36":{"start":{"line":211,"column":2},"end":{"line":231,"column":5}},"37":{"start":{"line":212,"column":20},"end":{"line":212,"column":43}},"38":{"start":{"line":213,"column":25},"end":{"line":213,"column":53}},"39":{"start":{"line":214,"column":4},"end":{"line":230,"column":6}}},"fnMap":{"0":{"name":"getInvoice","decl":{"start":{"line":30,"column":22},"end":{"line":30,"column":32}},"loc":{"start":{"line":35,"column":27},"end":{"line":84,"column":1}}},"1":{"name":"listInvoicesBySubmitter","decl":{"start":{"line":102,"column":22},"end":{"line":102,"column":45}},"loc":{"start":{"line":109,"column":23},"end":{"line":158,"column":1}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":137,"column":20},"end":{"line":137,"column":23}},"loc":{"start":{"line":137,"column":26},"end":{"line":157,"column":3}}},"3":{"name":"listInvoicesByLP","decl":{"start":{"line":176,"column":22},"end":{"line":176,"column":38}},"loc":{"start":{"line":183,"column":23},"end":{"line":232,"column":1}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":211,"column":20},"end":{"line":211,"column":23}},"loc":{"start":{"line":211,"column":26},"end":{"line":231,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":53,"column":2},"end":{"line":58,"column":3}},"type":"if","locations":[{"start":{"line":53,"column":2},"end":{"line":58,"column":3}}]},"1":{"loc":{"start":{"line":54,"column":4},"end":{"line":56,"column":5}},"type":"if","locations":[{"start":{"line":54,"column":4},"end":{"line":56,"column":5}}]},"2":{"loc":{"start":{"line":54,"column":8},"end":{"line":54,"column":98}},"type":"binary-expr","locations":[{"start":{"line":54,"column":8},"end":{"line":54,"column":46}},{"start":{"line":54,"column":50},"end":{"line":54,"column":98}}]},"3":{"loc":{"start":{"line":59,"column":2},"end":{"line":61,"column":3}},"type":"if","locations":[{"start":{"line":59,"column":2},"end":{"line":61,"column":3}}]},"4":{"loc":{"start":{"line":75,"column":13},"end":{"line":75,"column":71}},"type":"binary-expr","locations":[{"start":{"line":75,"column":13},"end":{"line":75,"column":39}},{"start":{"line":75,"column":43},"end":{"line":75,"column":71}}]},"5":{"loc":{"start":{"line":76,"column":12},"end":{"line":76,"column":61}},"type":"cond-expr","locations":[{"start":{"line":76,"column":28},"end":{"line":76,"column":49}},{"start":{"line":76,"column":52},"end":{"line":76,"column":61}}]},"6":{"loc":{"start":{"line":77,"column":14},"end":{"line":77,"column":69}},"type":"cond-expr","locations":[{"start":{"line":77,"column":33},"end":{"line":77,"column":57}},{"start":{"line":77,"column":60},"end":{"line":77,"column":69}}]},"7":{"loc":{"start":{"line":80,"column":18},"end":{"line":80,"column":109}},"type":"cond-expr","locations":[{"start":{"line":80,"column":41},"end":{"line":80,"column":97}},{"start":{"line":80,"column":100},"end":{"line":80,"column":109}}]},"8":{"loc":{"start":{"line":108,"column":2},"end":{"line":108,"column":18}},"type":"default-arg","locations":[{"start":{"line":108,"column":17},"end":{"line":108,"column":18}}]},"9":{"loc":{"start":{"line":109,"column":2},"end":{"line":109,"column":23}},"type":"default-arg","locations":[{"start":{"line":109,"column":21},"end":{"line":109,"column":23}}]},"10":{"loc":{"start":{"line":129,"column":2},"end":{"line":131,"column":3}},"type":"if","locations":[{"start":{"line":129,"column":2},"end":{"line":131,"column":3}}]},"11":{"loc":{"start":{"line":132,"column":2},"end":{"line":134,"column":3}},"type":"if","locations":[{"start":{"line":132,"column":2},"end":{"line":134,"column":3}}]},"12":{"loc":{"start":{"line":148,"column":15},"end":{"line":148,"column":73}},"type":"binary-expr","locations":[{"start":{"line":148,"column":15},"end":{"line":148,"column":41}},{"start":{"line":148,"column":45},"end":{"line":148,"column":73}}]},"13":{"loc":{"start":{"line":149,"column":14},"end":{"line":149,"column":63}},"type":"cond-expr","locations":[{"start":{"line":149,"column":30},"end":{"line":149,"column":51}},{"start":{"line":149,"column":54},"end":{"line":149,"column":63}}]},"14":{"loc":{"start":{"line":150,"column":16},"end":{"line":150,"column":71}},"type":"cond-expr","locations":[{"start":{"line":150,"column":35},"end":{"line":150,"column":59}},{"start":{"line":150,"column":62},"end":{"line":150,"column":71}}]},"15":{"loc":{"start":{"line":153,"column":20},"end":{"line":153,"column":111}},"type":"cond-expr","locations":[{"start":{"line":153,"column":43},"end":{"line":153,"column":99}},{"start":{"line":153,"column":102},"end":{"line":153,"column":111}}]},"16":{"loc":{"start":{"line":182,"column":2},"end":{"line":182,"column":18}},"type":"default-arg","locations":[{"start":{"line":182,"column":17},"end":{"line":182,"column":18}}]},"17":{"loc":{"start":{"line":183,"column":2},"end":{"line":183,"column":23}},"type":"default-arg","locations":[{"start":{"line":183,"column":21},"end":{"line":183,"column":23}}]},"18":{"loc":{"start":{"line":203,"column":2},"end":{"line":205,"column":3}},"type":"if","locations":[{"start":{"line":203,"column":2},"end":{"line":205,"column":3}}]},"19":{"loc":{"start":{"line":206,"column":2},"end":{"line":208,"column":3}},"type":"if","locations":[{"start":{"line":206,"column":2},"end":{"line":208,"column":3}}]},"20":{"loc":{"start":{"line":222,"column":15},"end":{"line":222,"column":73}},"type":"binary-expr","locations":[{"start":{"line":222,"column":15},"end":{"line":222,"column":41}},{"start":{"line":222,"column":45},"end":{"line":222,"column":73}}]},"21":{"loc":{"start":{"line":223,"column":14},"end":{"line":223,"column":63}},"type":"cond-expr","locations":[{"start":{"line":223,"column":30},"end":{"line":223,"column":51}},{"start":{"line":223,"column":54},"end":{"line":223,"column":63}}]},"22":{"loc":{"start":{"line":224,"column":16},"end":{"line":224,"column":71}},"type":"cond-expr","locations":[{"start":{"line":224,"column":35},"end":{"line":224,"column":59}},{"start":{"line":224,"column":62},"end":{"line":224,"column":71}}]},"23":{"loc":{"start":{"line":227,"column":20},"end":{"line":227,"column":111}},"type":"cond-expr","locations":[{"start":{"line":227,"column":43},"end":{"line":227,"column":99}},{"start":{"line":227,"column":102},"end":{"line":227,"column":111}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0],"1":[0],"2":[0,0],"3":[0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0],"9":[0],"10":[0],"11":[0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0],"17":[0],"18":[0],"19":[0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/reputation.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/reputation.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/reputation.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/reputation.ts","statementMap":{"0":{"start":{"line":47,"column":21},"end":{"line":47,"column":38}},"1":{"start":{"line":50,"column":2},"end":{"line":50,"column":36}},"2":{"start":{"line":84,"column":2},"end":{"line":88,"column":3}},"3":{"start":{"line":85,"column":4},"end":{"line":87,"column":6}},"4":{"start":{"line":90,"column":19},"end":{"line":90,"column":43}},"5":{"start":{"line":91,"column":13},"end":{"line":93,"column":null}},"6":{"start":{"line":96,"column":24},"end":{"line":98,"column":null}},"7":{"start":{"line":101,"column":16},"end":{"line":107,"column":12}},"8":{"start":{"line":109,"column":14},"end":{"line":109,"column":53}},"9":{"start":{"line":111,"column":2},"end":{"line":113,"column":3}},"10":{"start":{"line":112,"column":4},"end":{"line":112,"column":70}},"11":{"start":{"line":116,"column":2},"end":{"line":124,"column":3}},"12":{"start":{"line":117,"column":4},"end":{"line":123,"column":6}},"13":{"start":{"line":126,"column":14},"end":{"line":126,"column":73}},"14":{"start":{"line":128,"column":2},"end":{"line":134,"column":4}}},"fnMap":{"0":{"name":"isValidGAddress","decl":{"start":{"line":49,"column":9},"end":{"line":49,"column":24}},"loc":{"start":{"line":49,"column":40},"end":{"line":51,"column":1}}},"1":{"name":"getReputation","decl":{"start":{"line":78,"column":22},"end":{"line":78,"column":35}},"loc":{"start":{"line":82,"column":46},"end":{"line":135,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":82,"column":2},"end":{"line":82,"column":46}},"type":"default-arg","locations":[{"start":{"line":82,"column":30},"end":{"line":82,"column":46}}]},"1":{"loc":{"start":{"line":84,"column":2},"end":{"line":88,"column":3}},"type":"if","locations":[{"start":{"line":84,"column":2},"end":{"line":88,"column":3}}]},"2":{"loc":{"start":{"line":111,"column":2},"end":{"line":113,"column":3}},"type":"if","locations":[{"start":{"line":111,"column":2},"end":{"line":113,"column":3}}]},"3":{"loc":{"start":{"line":116,"column":2},"end":{"line":124,"column":3}},"type":"if","locations":[{"start":{"line":116,"column":2},"end":{"line":124,"column":3}}]},"4":{"loc":{"start":{"line":129,"column":20},"end":{"line":129,"column":45}},"type":"binary-expr","locations":[{"start":{"line":129,"column":20},"end":{"line":129,"column":34}},{"start":{"line":129,"column":38},"end":{"line":129,"column":45}}]},"5":{"loc":{"start":{"line":130,"column":18},"end":{"line":130,"column":35}},"type":"binary-expr","locations":[{"start":{"line":130,"column":18},"end":{"line":130,"column":30}},{"start":{"line":130,"column":34},"end":{"line":130,"column":35}}]},"6":{"loc":{"start":{"line":131,"column":30},"end":{"line":131,"column":60}},"type":"binary-expr","locations":[{"start":{"line":131,"column":30},"end":{"line":131,"column":55}},{"start":{"line":131,"column":59},"end":{"line":131,"column":60}}]},"7":{"loc":{"start":{"line":132,"column":25},"end":{"line":132,"column":50}},"type":"binary-expr","locations":[{"start":{"line":132,"column":25},"end":{"line":132,"column":45}},{"start":{"line":132,"column":49},"end":{"line":132,"column":50}}]},"8":{"loc":{"start":{"line":133,"column":30},"end":{"line":133,"column":60}},"type":"binary-expr","locations":[{"start":{"line":133,"column":30},"end":{"line":133,"column":55}},{"start":{"line":133,"column":59},"end":{"line":133,"column":60}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0},"f":{"0":0,"1":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/stats.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/stats.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/stats.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/stats.ts","statementMap":{"0":{"start":{"line":74,"column":19},"end":{"line":74,"column":43}},"1":{"start":{"line":75,"column":13},"end":{"line":75,"column":48}},"2":{"start":{"line":77,"column":24},"end":{"line":79,"column":null}},"3":{"start":{"line":82,"column":16},"end":{"line":88,"column":12}},"4":{"start":{"line":90,"column":14},"end":{"line":90,"column":53}},"5":{"start":{"line":92,"column":2},"end":{"line":94,"column":3}},"6":{"start":{"line":93,"column":4},"end":{"line":93,"column":74}},"7":{"start":{"line":96,"column":2},"end":{"line":107,"column":3}},"8":{"start":{"line":97,"column":4},"end":{"line":106,"column":6}},"9":{"start":{"line":109,"column":14},"end":{"line":109,"column":73}},"10":{"start":{"line":112,"column":48},"end":{"line":112,"column":50}},"11":{"start":{"line":113,"column":26},"end":{"line":113,"column":85}},"12":{"start":{"line":114,"column":2},"end":{"line":118,"column":3}},"13":{"start":{"line":115,"column":4},"end":{"line":117,"column":5}},"14":{"start":{"line":116,"column":6},"end":{"line":116,"column":44}},"15":{"start":{"line":120,"column":2},"end":{"line":131,"column":4}}},"fnMap":{"0":{"name":"getContractStats","decl":{"start":{"line":69,"column":22},"end":{"line":69,"column":38}},"loc":{"start":{"line":72,"column":46},"end":{"line":132,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":72,"column":2},"end":{"line":72,"column":46}},"type":"default-arg","locations":[{"start":{"line":72,"column":30},"end":{"line":72,"column":46}}]},"1":{"loc":{"start":{"line":92,"column":2},"end":{"line":94,"column":3}},"type":"if","locations":[{"start":{"line":92,"column":2},"end":{"line":94,"column":3}}]},"2":{"loc":{"start":{"line":96,"column":2},"end":{"line":107,"column":3}},"type":"if","locations":[{"start":{"line":96,"column":2},"end":{"line":107,"column":3}}]},"3":{"loc":{"start":{"line":114,"column":2},"end":{"line":118,"column":3}},"type":"if","locations":[{"start":{"line":114,"column":2},"end":{"line":118,"column":3}}]},"4":{"loc":{"start":{"line":121,"column":33},"end":{"line":121,"column":61}},"type":"binary-expr","locations":[{"start":{"line":121,"column":33},"end":{"line":121,"column":54}},{"start":{"line":121,"column":58},"end":{"line":121,"column":61}}]},"5":{"loc":{"start":{"line":122,"column":31},"end":{"line":122,"column":57}},"type":"binary-expr","locations":[{"start":{"line":122,"column":31},"end":{"line":122,"column":50}},{"start":{"line":122,"column":54},"end":{"line":122,"column":57}}]},"6":{"loc":{"start":{"line":123,"column":29},"end":{"line":123,"column":53}},"type":"binary-expr","locations":[{"start":{"line":123,"column":29},"end":{"line":123,"column":46}},{"start":{"line":123,"column":50},"end":{"line":123,"column":53}}]},"7":{"loc":{"start":{"line":124,"column":35},"end":{"line":124,"column":66}},"type":"binary-expr","locations":[{"start":{"line":124,"column":35},"end":{"line":124,"column":59}},{"start":{"line":124,"column":63},"end":{"line":124,"column":66}}]},"8":{"loc":{"start":{"line":125,"column":35},"end":{"line":125,"column":66}},"type":"binary-expr","locations":[{"start":{"line":125,"column":35},"end":{"line":125,"column":59}},{"start":{"line":125,"column":63},"end":{"line":125,"column":66}}]},"9":{"loc":{"start":{"line":126,"column":34},"end":{"line":126,"column":64}},"type":"binary-expr","locations":[{"start":{"line":126,"column":34},"end":{"line":126,"column":57}},{"start":{"line":126,"column":61},"end":{"line":126,"column":64}}]},"10":{"loc":{"start":{"line":129,"column":13},"end":{"line":129,"column":54}},"type":"binary-expr","locations":[{"start":{"line":129,"column":13},"end":{"line":129,"column":47}},{"start":{"line":129,"column":51},"end":{"line":129,"column":54}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"f":{"0":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/submitInvoice.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/submitInvoice.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/transferLPPosition.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/methods/transferLPPosition.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/FreighterSigner.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/FreighterSigner.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/FreighterSigner.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/FreighterSigner.ts","statementMap":{"0":{"start":{"line":64,"column":4},"end":{"line":64,"column":19}},"1":{"start":{"line":65,"column":4},"end":{"line":65,"column":27}},"2":{"start":{"line":66,"column":4},"end":{"line":66,"column":21}},"3":{"start":{"line":70,"column":4},"end":{"line":73,"column":6}},"4":{"start":{"line":77,"column":4},"end":{"line":80,"column":6}},"5":{"start":{"line":84,"column":4},"end":{"line":87,"column":6}},"6":{"start":{"line":91,"column":4},"end":{"line":94,"column":6}},"7":{"start":{"line":99,"column":0},"end":{"line":99,"column":null}},"8":{"start":{"line":100,"column":2},"end":{"line":100,"column":null}},"9":{"start":{"line":101,"column":2},"end":{"line":101,"column":null}},"10":{"start":{"line":102,"column":2},"end":{"line":102,"column":null}},"11":{"start":{"line":103,"column":2},"end":{"line":103,"column":null}},"12":{"start":{"line":104,"column":2},"end":{"line":104,"column":null}},"13":{"start":{"line":111,"column":56},"end":{"line":114,"column":2}},"14":{"start":{"line":116,"column":56},"end":{"line":120,"column":2}},"15":{"start":{"line":144,"column":10},"end":{"line":144,"column":43}},"16":{"start":{"line":145,"column":10},"end":{"line":145,"column":35}},"17":{"start":{"line":153,"column":4},"end":{"line":153,"column":53}},"18":{"start":{"line":169,"column":4},"end":{"line":169,"column":33}},"19":{"start":{"line":182,"column":4},"end":{"line":182,"column":28}},"20":{"start":{"line":184,"column":4},"end":{"line":187,"column":5}},"21":{"start":{"line":186,"column":6},"end":{"line":186,"column":36}},"22":{"start":{"line":191,"column":15},"end":{"line":191,"column":47}},"23":{"start":{"line":193,"column":4},"end":{"line":195,"column":5}},"24":{"start":{"line":194,"column":6},"end":{"line":194,"column":36}},"25":{"start":{"line":198,"column":4},"end":{"line":198,"column":32}},"26":{"start":{"line":200,"column":4},"end":{"line":200,"column":25}},"27":{"start":{"line":201,"column":4},"end":{"line":201,"column":33}},"28":{"start":{"line":202,"column":4},"end":{"line":202,"column":14}},"29":{"start":{"line":225,"column":4},"end":{"line":227,"column":5}},"30":{"start":{"line":226,"column":6},"end":{"line":226,"column":27}},"31":{"start":{"line":230,"column":23},"end":{"line":230,"column":58}},"32":{"start":{"line":232,"column":4},"end":{"line":236,"column":5}},"33":{"start":{"line":233,"column":6},"end":{"line":235,"column":8}},"34":{"start":{"line":239,"column":25},"end":{"line":241,"column":32}},"35":{"start":{"line":244,"column":29},"end":{"line":244,"column":77}},"36":{"start":{"line":245,"column":4},"end":{"line":249,"column":5}},"37":{"start":{"line":246,"column":6},"end":{"line":248,"column":8}},"38":{"start":{"line":252,"column":4},"end":{"line":258,"column":5}},"39":{"start":{"line":253,"column":6},"end":{"line":255,"column":9}},"40":{"start":{"line":257,"column":6},"end":{"line":257,"column":41}},"41":{"start":{"line":260,"column":4},"end":{"line":262,"column":5}},"42":{"start":{"line":261,"column":6},"end":{"line":261,"column":36}},"43":{"start":{"line":264,"column":4},"end":{"line":264,"column":21}},"44":{"start":{"line":273,"column":4},"end":{"line":273,"column":35}},"45":{"start":{"line":278,"column":4},"end":{"line":278,"column":61}},"46":{"start":{"line":289,"column":14},"end":{"line":289,"column":31}},"47":{"start":{"line":290,"column":4},"end":{"line":292,"column":5}},"48":{"start":{"line":291,"column":6},"end":{"line":291,"column":42}},"49":{"start":{"line":297,"column":4},"end":{"line":297,"column":28}},"50":{"start":{"line":299,"column":4},"end":{"line":299,"column":52}},"51":{"start":{"line":308,"column":4},"end":{"line":313,"column":5}},"52":{"start":{"line":309,"column":6},"end":{"line":309,"column":53}},"53":{"start":{"line":312,"column":6},"end":{"line":312,"column":13}},"54":{"start":{"line":315,"column":31},"end":{"line":315,"column":69}},"55":{"start":{"line":316,"column":4},"end":{"line":316,"column":36}},"56":{"start":{"line":316,"column":29},"end":{"line":316,"column":36}},"57":{"start":{"line":318,"column":4},"end":{"line":323,"column":5}},"58":{"start":{"line":319,"column":6},"end":{"line":322,"column":8}},"59":{"start":{"line":328,"column":16},"end":{"line":328,"column":77}},"60":{"start":{"line":330,"column":20},"end":{"line":330,"column":37}},"61":{"start":{"line":332,"column":4},"end":{"line":339,"column":5}},"62":{"start":{"line":338,"column":6},"end":{"line":338,"column":37}},"63":{"start":{"line":341,"column":4},"end":{"line":346,"column":5}},"64":{"start":{"line":345,"column":6},"end":{"line":345,"column":74}},"65":{"start":{"line":348,"column":4},"end":{"line":348,"column":87}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":63,"column":2},"end":{"line":63,"column":14}},"loc":{"start":{"line":63,"column":49},"end":{"line":67,"column":3}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":69,"column":2},"end":{"line":69,"column":8}},"loc":{"start":{"line":69,"column":27},"end":{"line":74,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":76,"column":2},"end":{"line":76,"column":8}},"loc":{"start":{"line":76,"column":21},"end":{"line":81,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":83,"column":2},"end":{"line":83,"column":8}},"loc":{"start":{"line":83,"column":57},"end":{"line":88,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":90,"column":2},"end":{"line":90,"column":8}},"loc":{"start":{"line":90,"column":21},"end":{"line":95,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":99,"column":0},"end":{"line":99,"column":6}},"loc":{"start":{"line":99,"column":24},"end":{"line":105,"column":1}}},"6":{"name":"(anonymous_6)","decl":{"start":{"line":152,"column":2},"end":{"line":152,"column":14}},"loc":{"start":{"line":152,"column":49},"end":{"line":154,"column":3}}},"7":{"name":"(anonymous_7)","decl":{"start":{"line":168,"column":2},"end":{"line":168,"column":6}},"loc":{"start":{"line":168,"column":15},"end":{"line":170,"column":3}}},"8":{"name":"(anonymous_8)","decl":{"start":{"line":181,"column":2},"end":{"line":181,"column":7}},"loc":{"start":{"line":181,"column":15},"end":{"line":203,"column":3}}},"9":{"name":"(anonymous_9)","decl":{"start":{"line":220,"column":2},"end":{"line":220,"column":7}},"loc":{"start":{"line":222,"column":29},"end":{"line":265,"column":3}}},"10":{"name":"(anonymous_10)","decl":{"start":{"line":272,"column":2},"end":{"line":272,"column":6}},"loc":{"start":{"line":272,"column":23},"end":{"line":274,"column":3}}},"11":{"name":"(anonymous_11)","decl":{"start":{"line":277,"column":2},"end":{"line":277,"column":6}},"loc":{"start":{"line":277,"column":17},"end":{"line":279,"column":3}}},"12":{"name":"(anonymous_12)","decl":{"start":{"line":286,"column":10},"end":{"line":286,"column":26}},"loc":{"start":{"line":286,"column":26},"end":{"line":293,"column":3}}},"13":{"name":"(anonymous_13)","decl":{"start":{"line":296,"column":10},"end":{"line":296,"column":14}},"loc":{"start":{"line":296,"column":14},"end":{"line":300,"column":3}}},"14":{"name":"(anonymous_14)","decl":{"start":{"line":306,"column":10},"end":{"line":306,"column":15}},"loc":{"start":{"line":306,"column":30},"end":{"line":324,"column":3}}},"15":{"name":"(anonymous_15)","decl":{"start":{"line":327,"column":10},"end":{"line":327,"column":28}},"loc":{"start":{"line":327,"column":41},"end":{"line":349,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":99,"column":12},"end":{"line":99,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":12},"end":{"line":99,"column":24}},{"start":{"line":99,"column":12},"end":{"line":99,"column":null}}]},"1":{"loc":{"start":{"line":169,"column":11},"end":{"line":169,"column":32}},"type":"binary-expr","locations":[{"start":{"line":169,"column":11},"end":{"line":169,"column":26}},{"start":{"line":169,"column":30},"end":{"line":169,"column":32}}]},"2":{"loc":{"start":{"line":184,"column":4},"end":{"line":187,"column":5}},"type":"if","locations":[{"start":{"line":184,"column":4},"end":{"line":187,"column":5}}]},"3":{"loc":{"start":{"line":193,"column":4},"end":{"line":195,"column":5}},"type":"if","locations":[{"start":{"line":193,"column":4},"end":{"line":195,"column":5}}]},"4":{"loc":{"start":{"line":193,"column":8},"end":{"line":193,"column":30}},"type":"binary-expr","locations":[{"start":{"line":193,"column":8},"end":{"line":193,"column":11}},{"start":{"line":193,"column":15},"end":{"line":193,"column":30}}]},"5":{"loc":{"start":{"line":225,"column":4},"end":{"line":227,"column":5}},"type":"if","locations":[{"start":{"line":225,"column":4},"end":{"line":227,"column":5}}]},"6":{"loc":{"start":{"line":232,"column":4},"end":{"line":236,"column":5}},"type":"if","locations":[{"start":{"line":232,"column":4},"end":{"line":236,"column":5}}]},"7":{"loc":{"start":{"line":245,"column":4},"end":{"line":249,"column":5}},"type":"if","locations":[{"start":{"line":245,"column":4},"end":{"line":249,"column":5}}]},"8":{"loc":{"start":{"line":260,"column":4},"end":{"line":262,"column":5}},"type":"if","locations":[{"start":{"line":260,"column":4},"end":{"line":262,"column":5}}]},"9":{"loc":{"start":{"line":260,"column":8},"end":{"line":260,"column":44}},"type":"binary-expr","locations":[{"start":{"line":260,"column":8},"end":{"line":260,"column":18}},{"start":{"line":260,"column":22},"end":{"line":260,"column":44}}]},"10":{"loc":{"start":{"line":278,"column":11},"end":{"line":278,"column":60}},"type":"binary-expr","locations":[{"start":{"line":278,"column":11},"end":{"line":278,"column":32}},{"start":{"line":278,"column":36},"end":{"line":278,"column":60}}]},"11":{"loc":{"start":{"line":290,"column":4},"end":{"line":292,"column":5}},"type":"if","locations":[{"start":{"line":290,"column":4},"end":{"line":292,"column":5}}]},"12":{"loc":{"start":{"line":290,"column":8},"end":{"line":290,"column":65}},"type":"binary-expr","locations":[{"start":{"line":290,"column":8},"end":{"line":290,"column":39}},{"start":{"line":290,"column":43},"end":{"line":290,"column":65}}]},"13":{"loc":{"start":{"line":316,"column":4},"end":{"line":316,"column":36}},"type":"if","locations":[{"start":{"line":316,"column":4},"end":{"line":316,"column":36}}]},"14":{"loc":{"start":{"line":318,"column":4},"end":{"line":323,"column":5}},"type":"if","locations":[{"start":{"line":318,"column":4},"end":{"line":323,"column":5}}]},"15":{"loc":{"start":{"line":328,"column":16},"end":{"line":328,"column":77}},"type":"cond-expr","locations":[{"start":{"line":328,"column":42},"end":{"line":328,"column":45}},{"start":{"line":328,"column":49},"end":{"line":328,"column":77}}]},"16":{"loc":{"start":{"line":328,"column":49},"end":{"line":328,"column":77}},"type":"binary-expr","locations":[{"start":{"line":328,"column":49},"end":{"line":328,"column":71}},{"start":{"line":328,"column":75},"end":{"line":328,"column":77}}]},"17":{"loc":{"start":{"line":332,"column":4},"end":{"line":339,"column":5}},"type":"if","locations":[{"start":{"line":332,"column":4},"end":{"line":339,"column":5}}]},"18":{"loc":{"start":{"line":333,"column":6},"end":{"line":336,"column":34}},"type":"binary-expr","locations":[{"start":{"line":333,"column":6},"end":{"line":333,"column":34}},{"start":{"line":334,"column":6},"end":{"line":334,"column":32}},{"start":{"line":335,"column":6},"end":{"line":335,"column":35}},{"start":{"line":336,"column":6},"end":{"line":336,"column":34}}]},"19":{"loc":{"start":{"line":341,"column":4},"end":{"line":346,"column":5}},"type":"if","locations":[{"start":{"line":341,"column":4},"end":{"line":346,"column":5}}]},"20":{"loc":{"start":{"line":342,"column":6},"end":{"line":343,"column":65}},"type":"binary-expr","locations":[{"start":{"line":342,"column":6},"end":{"line":342,"column":42}},{"start":{"line":343,"column":7},"end":{"line":343,"column":34}},{"start":{"line":343,"column":38},"end":{"line":343,"column":64}}]},"21":{"loc":{"start":{"line":348,"column":52},"end":{"line":348,"column":85}},"type":"binary-expr","locations":[{"start":{"line":348,"column":52},"end":{"line":348,"column":55}},{"start":{"line":348,"column":59},"end":{"line":348,"column":85}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"b":{"0":[0,0],"1":[0,0],"2":[0],"3":[0],"4":[0,0],"5":[0],"6":[0],"7":[0],"8":[0],"9":[0,0],"10":[0,0],"11":[0],"12":[0,0],"13":[0],"14":[0],"15":[0,0],"16":[0,0],"17":[0],"18":[0,0,0,0],"19":[0],"20":[0,0,0],"21":[0,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/ISigner.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/ISigner.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/KeypairSigner.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/KeypairSigner.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/KeypairSigner.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/signers/KeypairSigner.ts","statementMap":{"0":{"start":{"line":34,"column":2},"end":{"line":38,"column":4}},"1":{"start":{"line":49,"column":2},"end":{"line":49,"column":34}},"2":{"start":{"line":49,"column":27},"end":{"line":49,"column":34}},"3":{"start":{"line":52,"column":24},"end":{"line":55,"column":4}},"4":{"start":{"line":57,"column":2},"end":{"line":63,"column":3}},"5":{"start":{"line":58,"column":4},"end":{"line":61,"column":6}},"6":{"start":{"line":62,"column":4},"end":{"line":62,"column":11}},"7":{"start":{"line":66,"column":2},"end":{"line":70,"column":4}},"8":{"start":{"line":102,"column":4},"end":{"line":107,"column":5}},"9":{"start":{"line":103,"column":6},"end":{"line":103,"column":45}},"10":{"start":{"line":104,"column":6},"end":{"line":104,"column":58}},"11":{"start":{"line":106,"column":6},"end":{"line":106,"column":38}},"12":{"start":{"line":116,"column":4},"end":{"line":116,"column":37}},"13":{"start":{"line":140,"column":23},"end":{"line":140,"column":58}},"14":{"start":{"line":142,"column":4},"end":{"line":146,"column":5}},"15":{"start":{"line":143,"column":6},"end":{"line":145,"column":8}},"16":{"start":{"line":149,"column":5},"end":{"line":149,"column":52}},"17":{"start":{"line":152,"column":4},"end":{"line":152,"column":68}},"18":{"start":{"line":168,"column":4},"end":{"line":168,"column":25}},"19":{"start":{"line":183,"column":19},"end":{"line":183,"column":38}},"20":{"start":{"line":184,"column":4},"end":{"line":188,"column":5}},"21":{"start":{"line":185,"column":6},"end":{"line":187,"column":8}},"22":{"start":{"line":190,"column":15},"end":{"line":190,"column":41}},"23":{"start":{"line":191,"column":4},"end":{"line":191,"column":33}}},"fnMap":{"0":{"name":"isTestEnvironment","decl":{"start":{"line":33,"column":9},"end":{"line":33,"column":26}},"loc":{"start":{"line":33,"column":26},"end":{"line":39,"column":1}}},"1":{"name":"warnIfHardcodedSecret","decl":{"start":{"line":48,"column":9},"end":{"line":48,"column":30}},"loc":{"start":{"line":48,"column":45},"end":{"line":71,"column":1}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":101,"column":2},"end":{"line":101,"column":14}},"loc":{"start":{"line":101,"column":47},"end":{"line":108,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":115,"column":2},"end":{"line":115,"column":6}},"loc":{"start":{"line":115,"column":15},"end":{"line":117,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":135,"column":2},"end":{"line":135,"column":7}},"loc":{"start":{"line":137,"column":29},"end":{"line":153,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":167,"column":2},"end":{"line":167,"column":6}},"loc":{"start":{"line":167,"column":13},"end":{"line":169,"column":3}}},"6":{"name":"(anonymous_6)","decl":{"start":{"line":182,"column":2},"end":{"line":182,"column":8}},"loc":{"start":{"line":182,"column":31},"end":{"line":192,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":4},"end":{"line":37,"column":39}},"type":"binary-expr","locations":[{"start":{"line":35,"column":4},"end":{"line":35,"column":38}},{"start":{"line":36,"column":4},"end":{"line":36,"column":47}},{"start":{"line":37,"column":4},"end":{"line":37,"column":39}}]},"1":{"loc":{"start":{"line":49,"column":2},"end":{"line":49,"column":34}},"type":"if","locations":[{"start":{"line":49,"column":2},"end":{"line":49,"column":34}}]},"2":{"loc":{"start":{"line":57,"column":2},"end":{"line":63,"column":3}},"type":"if","locations":[{"start":{"line":57,"column":2},"end":{"line":63,"column":3}}]},"3":{"loc":{"start":{"line":102,"column":4},"end":{"line":107,"column":5}},"type":"if","locations":[{"start":{"line":102,"column":4},"end":{"line":107,"column":5}},{"start":{"line":105,"column":11},"end":{"line":107,"column":5}}]},"4":{"loc":{"start":{"line":142,"column":4},"end":{"line":146,"column":5}},"type":"if","locations":[{"start":{"line":142,"column":4},"end":{"line":146,"column":5}}]},"5":{"loc":{"start":{"line":184,"column":4},"end":{"line":188,"column":5}},"type":"if","locations":[{"start":{"line":184,"column":4},"end":{"line":188,"column":5}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0,0],"1":[0],"2":[0],"3":[0,0],"4":[0],"5":[0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/governance.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/governance.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/governance.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/governance.ts","statementMap":{"0":{"start":{"line":15,"column":0},"end":{"line":15,"column":null}},"1":{"start":{"line":17,"column":2},"end":{"line":17,"column":null}},"2":{"start":{"line":19,"column":2},"end":{"line":19,"column":null}},"3":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"4":{"start":{"line":23,"column":2},"end":{"line":23,"column":null}},"5":{"start":{"line":25,"column":2},"end":{"line":25,"column":null}},"6":{"start":{"line":27,"column":2},"end":{"line":27,"column":null}},"7":{"start":{"line":31,"column":0},"end":{"line":31,"column":null}},"8":{"start":{"line":32,"column":2},"end":{"line":32,"column":null}},"9":{"start":{"line":33,"column":2},"end":{"line":33,"column":null}},"10":{"start":{"line":34,"column":2},"end":{"line":34,"column":null}},"11":{"start":{"line":35,"column":2},"end":{"line":35,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":15,"column":0},"end":{"line":15,"column":6}},"loc":{"start":{"line":15,"column":26},"end":{"line":28,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":31,"column":0},"end":{"line":31,"column":6}},"loc":{"start":{"line":31,"column":26},"end":{"line":36,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":12},"end":{"line":15,"column":null}},"type":"binary-expr","locations":[{"start":{"line":15,"column":12},"end":{"line":15,"column":26}},{"start":{"line":15,"column":12},"end":{"line":15,"column":null}}]},"1":{"loc":{"start":{"line":31,"column":12},"end":{"line":31,"column":null}},"type":"binary-expr","locations":[{"start":{"line":31,"column":12},"end":{"line":31,"column":26}},{"start":{"line":31,"column":12},"end":{"line":31,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"f":{"0":0,"1":0},"b":{"0":[0,0],"1":[0,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/invoice.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/invoice.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/params.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/types/params.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/allowance.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/allowance.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/allowance.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/allowance.ts","statementMap":{"0":{"start":{"line":45,"column":24},"end":{"line":45,"column":57}},"1":{"start":{"line":47,"column":13},"end":{"line":50,"column":null}},"2":{"start":{"line":53,"column":13},"end":{"line":59,"column":12}},"3":{"start":{"line":61,"column":20},"end":{"line":61,"column":56}},"4":{"start":{"line":63,"column":2},"end":{"line":65,"column":3}},"5":{"start":{"line":64,"column":4},"end":{"line":64,"column":71}},"6":{"start":{"line":67,"column":2},"end":{"line":69,"column":3}},"7":{"start":{"line":68,"column":4},"end":{"line":68,"column":47}},"8":{"start":{"line":71,"column":17},"end":{"line":71,"column":55}},"9":{"start":{"line":74,"column":2},"end":{"line":80,"column":3}},"10":{"start":{"line":75,"column":16},"end":{"line":75,"column":49}},"11":{"start":{"line":76,"column":4},"end":{"line":79,"column":6}},"12":{"start":{"line":83,"column":2},"end":{"line":86,"column":4}},"13":{"start":{"line":120,"column":24},"end":{"line":120,"column":50}},"14":{"start":{"line":123,"column":21},"end":{"line":123,"column":51}},"15":{"start":{"line":124,"column":27},"end":{"line":124,"column":52}},"16":{"start":{"line":126,"column":13},"end":{"line":131,"column":null}},"17":{"start":{"line":134,"column":13},"end":{"line":140,"column":12}},"18":{"start":{"line":142,"column":21},"end":{"line":142,"column":56}},"19":{"start":{"line":143,"column":2},"end":{"line":143,"column":58}},"20":{"start":{"line":167,"column":2},"end":{"line":167,"column":48}},"21":{"start":{"line":167,"column":35},"end":{"line":167,"column":48}},"22":{"start":{"line":169,"column":2},"end":{"line":175,"column":3}},"23":{"start":{"line":174,"column":4},"end":{"line":174,"column":17}},"24":{"start":{"line":177,"column":2},"end":{"line":177,"column":14}}},"fnMap":{"0":{"name":"getAllowance","decl":{"start":{"line":40,"column":22},"end":{"line":40,"column":34}},"loc":{"start":{"line":43,"column":24},"end":{"line":87,"column":1}}},"1":{"name":"buildApproveTransaction","decl":{"start":{"line":112,"column":22},"end":{"line":112,"column":45}},"loc":{"start":{"line":118,"column":46},"end":{"line":144,"column":1}}},"2":{"name":"isAllowanceSufficient","decl":{"start":{"line":162,"column":16},"end":{"line":162,"column":37}},"loc":{"start":{"line":165,"column":30},"end":{"line":178,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":63,"column":2},"end":{"line":65,"column":3}},"type":"if","locations":[{"start":{"line":63,"column":2},"end":{"line":65,"column":3}}]},"1":{"loc":{"start":{"line":67,"column":2},"end":{"line":69,"column":3}},"type":"if","locations":[{"start":{"line":67,"column":2},"end":{"line":69,"column":3}}]},"2":{"loc":{"start":{"line":74,"column":2},"end":{"line":80,"column":3}},"type":"if","locations":[{"start":{"line":74,"column":2},"end":{"line":80,"column":3}}]},"3":{"loc":{"start":{"line":74,"column":6},"end":{"line":74,"column":73}},"type":"binary-expr","locations":[{"start":{"line":74,"column":6},"end":{"line":74,"column":32}},{"start":{"line":74,"column":36},"end":{"line":74,"column":51}},{"start":{"line":74,"column":55},"end":{"line":74,"column":73}}]},"4":{"loc":{"start":{"line":78,"column":31},"end":{"line":78,"column":60}},"type":"binary-expr","locations":[{"start":{"line":78,"column":31},"end":{"line":78,"column":55}},{"start":{"line":78,"column":59},"end":{"line":78,"column":60}}]},"5":{"loc":{"start":{"line":118,"column":2},"end":{"line":118,"column":46}},"type":"default-arg","locations":[{"start":{"line":118,"column":30},"end":{"line":118,"column":46}}]},"6":{"loc":{"start":{"line":167,"column":2},"end":{"line":167,"column":48}},"type":"if","locations":[{"start":{"line":167,"column":2},"end":{"line":167,"column":48}}]},"7":{"loc":{"start":{"line":169,"column":2},"end":{"line":175,"column":3}},"type":"if","locations":[{"start":{"line":169,"column":2},"end":{"line":175,"column":3}}]},"8":{"loc":{"start":{"line":170,"column":4},"end":{"line":172,"column":52}},"type":"binary-expr","locations":[{"start":{"line":170,"column":4},"end":{"line":170,"column":37}},{"start":{"line":171,"column":4},"end":{"line":171,"column":34}},{"start":{"line":172,"column":4},"end":{"line":172,"column":52}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0},"f":{"0":0,"1":0,"2":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0,0,0],"4":[0,0],"5":[0],"6":[0],"7":[0],"8":[0,0,0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/tokenRegistry.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/tokenRegistry.ts","statementMap":{"0":{"start":{"line":22,"column":65},"end":{"line":63,"column":2}},"1":{"start":{"line":69,"column":4},"end":{"line":69,"column":27}},"2":{"start":{"line":77,"column":18},"end":{"line":77,"column":62}},"3":{"start":{"line":78,"column":4},"end":{"line":83,"column":5}},"4":{"start":{"line":79,"column":6},"end":{"line":82,"column":8}},"5":{"start":{"line":84,"column":4},"end":{"line":84,"column":17}},"6":{"start":{"line":89,"column":4},"end":{"line":89,"column":49}},"7":{"start":{"line":97,"column":4},"end":{"line":97,"column":61}},"8":{"start":{"line":105,"column":25},"end":{"line":105,"column":41}},"9":{"start":{"line":106,"column":4},"end":{"line":106,"column":60}},"10":{"start":{"line":114,"column":25},"end":{"line":114,"column":41}},"11":{"start":{"line":115,"column":4},"end":{"line":115,"column":47}},"12":{"start":{"line":120,"column":29},"end":{"line":120,"column":57}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":68,"column":2},"end":{"line":68,"column":14}},"loc":{"start":{"line":68,"column":46},"end":{"line":70,"column":3}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":76,"column":2},"end":{"line":76,"column":5}},"loc":{"start":{"line":76,"column":20},"end":{"line":85,"column":3}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":88,"column":2},"end":{"line":88,"column":6}},"loc":{"start":{"line":88,"column":6},"end":{"line":90,"column":3}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":96,"column":2},"end":{"line":96,"column":10}},"loc":{"start":{"line":96,"column":26},"end":{"line":98,"column":3}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":104,"column":2},"end":{"line":104,"column":13}},"loc":{"start":{"line":104,"column":49},"end":{"line":107,"column":3}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":113,"column":2},"end":{"line":113,"column":15}},"loc":{"start":{"line":113,"column":50},"end":{"line":116,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":68,"column":14},"end":{"line":68,"column":46}},"type":"default-arg","locations":[{"start":{"line":68,"column":37},"end":{"line":68,"column":46}}]},"1":{"loc":{"start":{"line":78,"column":4},"end":{"line":83,"column":5}},"type":"if","locations":[{"start":{"line":78,"column":4},"end":{"line":83,"column":5}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0],"1":[0]}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/validate.d.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/validate.d.ts","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{}} +,"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/validate.ts": {"path":"/Users/ucheekezie/myworks/web3work/drips/burner8/ILN-Smart-Contract/sdk/src/utils/validate.ts","statementMap":{"0":{"start":{"line":16,"column":25},"end":{"line":16,"column":27}},"1":{"start":{"line":18,"column":25},"end":{"line":18,"column":27}},"2":{"start":{"line":21,"column":32},"end":{"line":21,"column":33}},"3":{"start":{"line":23,"column":32},"end":{"line":23,"column":36}},"4":{"start":{"line":26,"column":31},"end":{"line":26,"column":50}},"5":{"start":{"line":28,"column":31},"end":{"line":28,"column":56}},"6":{"start":{"line":31,"column":47},"end":{"line":35,"column":2}},"7":{"start":{"line":45,"column":2},"end":{"line":47,"column":3}},"8":{"start":{"line":46,"column":4},"end":{"line":46,"column":76}},"9":{"start":{"line":48,"column":2},"end":{"line":52,"column":3}},"10":{"start":{"line":49,"column":4},"end":{"line":51,"column":6}},"11":{"start":{"line":53,"column":2},"end":{"line":57,"column":3}},"12":{"start":{"line":54,"column":4},"end":{"line":56,"column":6}},"13":{"start":{"line":67,"column":2},"end":{"line":69,"column":3}},"14":{"start":{"line":68,"column":4},"end":{"line":68,"column":80}},"15":{"start":{"line":70,"column":2},"end":{"line":74,"column":3}},"16":{"start":{"line":71,"column":4},"end":{"line":73,"column":6}},"17":{"start":{"line":91,"column":2},"end":{"line":93,"column":3}},"18":{"start":{"line":92,"column":4},"end":{"line":92,"column":83}},"19":{"start":{"line":94,"column":2},"end":{"line":96,"column":3}},"20":{"start":{"line":95,"column":4},"end":{"line":95,"column":70}},"21":{"start":{"line":97,"column":2},"end":{"line":101,"column":3}},"22":{"start":{"line":98,"column":4},"end":{"line":100,"column":6}},"23":{"start":{"line":105,"column":19},"end":{"line":105,"column":40}},"24":{"start":{"line":106,"column":2},"end":{"line":110,"column":3}},"25":{"start":{"line":107,"column":4},"end":{"line":109,"column":6}},"26":{"start":{"line":120,"column":2},"end":{"line":122,"column":3}},"27":{"start":{"line":121,"column":4},"end":{"line":121,"column":85}},"28":{"start":{"line":123,"column":2},"end":{"line":127,"column":3}},"29":{"start":{"line":124,"column":4},"end":{"line":126,"column":6}},"30":{"start":{"line":139,"column":2},"end":{"line":141,"column":3}},"31":{"start":{"line":140,"column":4},"end":{"line":140,"column":71}},"32":{"start":{"line":142,"column":16},"end":{"line":142,"column":43}},"33":{"start":{"line":143,"column":2},"end":{"line":145,"column":3}},"34":{"start":{"line":144,"column":4},"end":{"line":144,"column":85}},"35":{"start":{"line":146,"column":2},"end":{"line":148,"column":3}},"36":{"start":{"line":147,"column":4},"end":{"line":147,"column":82}}},"fnMap":{"0":{"name":"validateGAddress","decl":{"start":{"line":44,"column":16},"end":{"line":44,"column":32}},"loc":{"start":{"line":44,"column":48},"end":{"line":58,"column":1}}},"1":{"name":"validateContractId","decl":{"start":{"line":66,"column":16},"end":{"line":66,"column":34}},"loc":{"start":{"line":66,"column":53},"end":{"line":75,"column":1}}},"2":{"name":"validateAmount","decl":{"start":{"line":86,"column":16},"end":{"line":86,"column":30}},"loc":{"start":{"line":89,"column":23},"end":{"line":111,"column":1}}},"3":{"name":"validateDiscountRate","decl":{"start":{"line":119,"column":16},"end":{"line":119,"column":36}},"loc":{"start":{"line":119,"column":49},"end":{"line":128,"column":1}}},"4":{"name":"validateDueDate","decl":{"start":{"line":138,"column":16},"end":{"line":138,"column":31}},"loc":{"start":{"line":138,"column":42},"end":{"line":149,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":45,"column":2},"end":{"line":47,"column":3}},"type":"if","locations":[{"start":{"line":45,"column":2},"end":{"line":47,"column":3}}]},"1":{"loc":{"start":{"line":45,"column":6},"end":{"line":45,"column":57}},"type":"binary-expr","locations":[{"start":{"line":45,"column":6},"end":{"line":45,"column":33}},{"start":{"line":45,"column":37},"end":{"line":45,"column":57}}]},"2":{"loc":{"start":{"line":48,"column":2},"end":{"line":52,"column":3}},"type":"if","locations":[{"start":{"line":48,"column":2},"end":{"line":52,"column":3}}]},"3":{"loc":{"start":{"line":53,"column":2},"end":{"line":57,"column":3}},"type":"if","locations":[{"start":{"line":53,"column":2},"end":{"line":57,"column":3}}]},"4":{"loc":{"start":{"line":67,"column":2},"end":{"line":69,"column":3}},"type":"if","locations":[{"start":{"line":67,"column":2},"end":{"line":69,"column":3}}]},"5":{"loc":{"start":{"line":67,"column":6},"end":{"line":67,"column":63}},"type":"binary-expr","locations":[{"start":{"line":67,"column":6},"end":{"line":67,"column":36}},{"start":{"line":67,"column":40},"end":{"line":67,"column":63}}]},"6":{"loc":{"start":{"line":70,"column":2},"end":{"line":74,"column":3}},"type":"if","locations":[{"start":{"line":70,"column":2},"end":{"line":74,"column":3}}]},"7":{"loc":{"start":{"line":70,"column":6},"end":{"line":70,"column":75}},"type":"binary-expr","locations":[{"start":{"line":70,"column":6},"end":{"line":70,"column":33}},{"start":{"line":70,"column":37},"end":{"line":70,"column":75}}]},"8":{"loc":{"start":{"line":91,"column":2},"end":{"line":93,"column":3}},"type":"if","locations":[{"start":{"line":91,"column":2},"end":{"line":93,"column":3}}]},"9":{"loc":{"start":{"line":94,"column":2},"end":{"line":96,"column":3}},"type":"if","locations":[{"start":{"line":94,"column":2},"end":{"line":96,"column":3}}]},"10":{"loc":{"start":{"line":97,"column":2},"end":{"line":101,"column":3}},"type":"if","locations":[{"start":{"line":97,"column":2},"end":{"line":101,"column":3}}]},"11":{"loc":{"start":{"line":106,"column":2},"end":{"line":110,"column":3}},"type":"if","locations":[{"start":{"line":106,"column":2},"end":{"line":110,"column":3}}]},"12":{"loc":{"start":{"line":106,"column":6},"end":{"line":106,"column":54}},"type":"binary-expr","locations":[{"start":{"line":106,"column":6},"end":{"line":106,"column":28}},{"start":{"line":106,"column":32},"end":{"line":106,"column":54}}]},"13":{"loc":{"start":{"line":120,"column":2},"end":{"line":122,"column":3}},"type":"if","locations":[{"start":{"line":120,"column":2},"end":{"line":122,"column":3}}]},"14":{"loc":{"start":{"line":123,"column":2},"end":{"line":127,"column":3}},"type":"if","locations":[{"start":{"line":123,"column":2},"end":{"line":127,"column":3}}]},"15":{"loc":{"start":{"line":123,"column":6},"end":{"line":123,"column":56}},"type":"binary-expr","locations":[{"start":{"line":123,"column":6},"end":{"line":123,"column":29}},{"start":{"line":123,"column":33},"end":{"line":123,"column":56}}]},"16":{"loc":{"start":{"line":139,"column":2},"end":{"line":141,"column":3}},"type":"if","locations":[{"start":{"line":139,"column":2},"end":{"line":141,"column":3}}]},"17":{"loc":{"start":{"line":139,"column":6},"end":{"line":139,"column":61}},"type":"binary-expr","locations":[{"start":{"line":139,"column":6},"end":{"line":139,"column":29}},{"start":{"line":139,"column":33},"end":{"line":139,"column":61}}]},"18":{"loc":{"start":{"line":143,"column":2},"end":{"line":145,"column":3}},"type":"if","locations":[{"start":{"line":143,"column":2},"end":{"line":145,"column":3}}]},"19":{"loc":{"start":{"line":146,"column":2},"end":{"line":148,"column":3}},"type":"if","locations":[{"start":{"line":146,"column":2},"end":{"line":148,"column":3}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0],"1":[0,0],"2":[0],"3":[0],"4":[0],"5":[0,0],"6":[0],"7":[0,0],"8":[0],"9":[0],"10":[0],"11":[0],"12":[0,0],"13":[0],"14":[0],"15":[0,0],"16":[0],"17":[0,0],"18":[0],"19":[0]}} +} diff --git a/sdk/coverage/lcov-report/base.css b/sdk/coverage/lcov-report/base.css new file mode 100644 index 00000000..f418035b --- /dev/null +++ b/sdk/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/sdk/coverage/lcov-report/block-navigation.js b/sdk/coverage/lcov-report/block-navigation.js new file mode 100644 index 00000000..530d1ed2 --- /dev/null +++ b/sdk/coverage/lcov-report/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selector that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/sdk/coverage/lcov-report/favicon.png b/sdk/coverage/lcov-report/favicon.png new file mode 100644 index 00000000..c1525b81 Binary files /dev/null and b/sdk/coverage/lcov-report/favicon.png differ diff --git a/sdk/coverage/lcov-report/index.html b/sdk/coverage/lcov-report/index.html new file mode 100644 index 00000000..4e30f329 --- /dev/null +++ b/sdk/coverage/lcov-report/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 0% + Statements + 0/397 +
+ + +
+ 0% + Branches + 0/249 +
+ + +
+ 0% + Functions + 0/100 +
+ + +
+ 0% + Lines + 0/354 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
0%0/1490%0/890%0/530%0/109
src/events +
+
0%0/00%0/00%0/00%0/0
src/methods +
+
0%0/710%0/690%0/80%0/71
src/signers +
+
0%0/900%0/450%0/230%0/88
src/types +
+
0%0/120%0/40%0/20%0/12
src/utils +
+
0%0/750%0/420%0/140%0/74
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/prettify.css b/sdk/coverage/lcov-report/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/sdk/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/sdk/coverage/lcov-report/prettify.js b/sdk/coverage/lcov-report/prettify.js new file mode 100644 index 00000000..b3225238 --- /dev/null +++ b/sdk/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/sdk/coverage/lcov-report/sort-arrow-sprite.png b/sdk/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 00000000..6ed68316 Binary files /dev/null and b/sdk/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/sdk/coverage/lcov-report/sorter.js b/sdk/coverage/lcov-report/sorter.js new file mode 100644 index 00000000..4ed70ae5 --- /dev/null +++ b/sdk/coverage/lcov-report/sorter.js @@ -0,0 +1,210 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + + // Try to create a RegExp from the searchValue. If it fails (invalid regex), + // it will be treated as a plain text search + let searchRegex; + try { + searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive + } catch (error) { + searchRegex = null; + } + + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + let isMatch = false; + + if (searchRegex) { + // If a valid regex was created, use it for matching + isMatch = searchRegex.test(row.textContent); + } else { + // Otherwise, fall back to the original plain text search + isMatch = row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()); + } + + row.style.display = isMatch ? '' : 'none'; + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/sdk/coverage/lcov-report/src/client.d.ts.html b/sdk/coverage/lcov-report/src/client.d.ts.html new file mode 100644 index 00000000..65c2eed8 --- /dev/null +++ b/sdk/coverage/lcov-report/src/client.d.ts.html @@ -0,0 +1,541 @@ + + + + + + Code coverage report for src/client.d.ts + + + + + + + + + +
+
+

All files / src client.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * ILNClient — entry point for the Invoice Liquidity Network SDK.
+ *
+ * Provides factory methods for common environments so integrators can
+ * get started with a one-liner:
+ *
+ * ```ts
+ * import { ILNClient } from "@iln/sdk";
+ *
+ * const client = ILNClient.testnet(signer);
+ * const reputation = await client.getReputation("G...");
+ * ```
+ *
+ * ## Architecture
+ *
+ * `ILNClient` is a thin wrapper around the SDK's free functions. It holds
+ * the RPC server, network passphrase, contract address, and signer so
+ * every method call uses the same configuration automatically.
+ */
+import { SorobanRpc } from "@stellar/stellar-sdk";
+import type { ISigner } from "./signers/ISigner.js";
+/**
+ * Public Soroban RPC endpoint for Stellar Testnet.
+ */
+export declare const TESTNET_RPC_URL = "https://soroban-testnet.stellar.org";
+/**
+ * Public Soroban RPC endpoint for Stellar Mainnet (Pubnet).
+ */
+export declare const MAINNET_RPC_URL = "https://soroban.stellar.org";
+/** Full configuration for a custom ILNClient. */
+export interface ILNClientConfig {
+    /** Soroban RPC endpoint URL. */
+    rpcUrl: string;
+    /** Stellar network passphrase (e.g. `Networks.TESTNET`). */
+    networkPassphrase: string;
+    /** Deployed invoice-liquidity contract address. */
+    contractId: string;
+    /**
+     * Optional signer for methods that require authentication (e.g. fundInvoice).
+     * Read-only methods like getReputation work without a signer.
+     */
+    signer?: ISigner;
+}
+/**
+ * Configured SDK client bound to a specific network and contract.
+ *
+ * @example
+ * ```ts
+ * // Testnet
+ * const client = ILNClient.testnet(mySigner);
+ *
+ * // Custom RPC (e.g. local validator node)
+ * const client = ILNClient.custom({
+ *   rpcUrl: "http://localhost:8000/soroban/rpc",
+ *   networkPassphrase: Networks.STANDALONE,
+ *   contractId: "CDEPLOYED...",
+ *   signer: mySigner,
+ * });
+ * ```
+ */
+export declare class ILNClient {
+    /** Soroban RPC server instance. */
+    readonly rpc: SorobanRpc.Server;
+    /** Stellar network passphrase. */
+    readonly networkPassphrase: string;
+    /** Deployed invoice-liquidity contract address. */
+    readonly contractId: string;
+    /** Optional signer for authenticated methods. */
+    readonly signer?: ISigner;
+    private _getReputation?;
+    private _getContractStats?;
+    constructor(config: ILNClientConfig);
+    /**
+     * Create a client pre-configured for Stellar Testnet.
+     *
+     * @param signer   - Optional signer for authenticated methods
+     * @param options  - Override defaults (rpcUrl, contractId)
+     *
+     * @example
+     * ```ts
+     * const client = ILNClient.testnet(freighterSigner);
+     * ```
+     */
+    static testnet(signer?: ISigner, options?: {
+        rpcUrl?: string;
+        contractId?: string;
+    }): ILNClient;
+    /**
+     * Create a client pre-configured for Stellar Mainnet (Pubnet).
+     *
+     * @param signer   - Optional signer for authenticated methods
+     * @param options  - Override defaults (rpcUrl, contractId)
+     *
+     * @example
+     * ```ts
+     * const client = ILNClient.mainnet(freighterSigner);
+     * ```
+     */
+    static mainnet(signer?: ISigner, options?: {
+        rpcUrl?: string;
+        contractId?: string;
+    }): ILNClient;
+    /**
+     * Create a client with fully custom configuration.
+     *
+     * Use this for local development (standalone network), Futurenet, or
+     * private Stellar deployments.
+     *
+     * @param config - Full ILNClientConfig
+     */
+    static custom(config: ILNClientConfig): ILNClient;
+    /**
+     * Fetch the detailed reputation profile for an address.
+     *
+     * Read-only; does not require a signer.
+     *
+     * @param address - Stellar G… address to query
+     * @returns ReputationProfile (zeroed for unknown addresses)
+     */
+    getReputation(address: string): Promise<import("./methods/reputation.js").ReputationProfile>;
+    /**
+     * Fetch protocol-wide statistics.
+     *
+     * Read-only; does not require a signer.
+     *
+     * @returns ContractStats
+     */
+    getContractStats(): Promise<import("./methods/stats.js").ContractStats>;
+}
+/**
+ * Default ILNClient singleton.
+ *
+ * Must be initialised via `iln.configure(...)` before use.
+ *
+ * @example
+ * ```ts
+ * import { iln } from "@iln/sdk";
+ *
+ * iln.configure({ rpcUrl: "...", networkPassphrase: Networks.TESTNET, contractId: "..." });
+ * await iln.getReputation("G...");
+ * ```
+ */
+declare class ILNSingleton {
+    private _client;
+    configure(config: ILNClientConfig): void;
+    /** Access the underlying client. Throws if not configured. */
+    get client(): ILNClient;
+    getReputation(address: string): Promise<import("./methods/reputation.js").ReputationProfile>;
+    getContractStats(): Promise<import("./methods/stats.js").ContractStats>;
+}
+export declare const iln: ILNSingleton;
+export {};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/client.test.d.ts.html b/sdk/coverage/lcov-report/src/client.test.d.ts.html new file mode 100644 index 00000000..40e6912c --- /dev/null +++ b/sdk/coverage/lcov-report/src/client.test.d.ts.html @@ -0,0 +1,106 @@ + + + + + + Code coverage report for src/client.test.d.ts + + + + + + + + + +
+
+

All files / src client.test.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8  +  +  +  +  +  +  + 
/**
+ * Tests for ILNClient — covers:
+ *   - testnet / mainnet / custom factory methods
+ *   - singleton iln.configure / iln.getReputation / iln.getContractStats
+ *   - Preset defaults (RPC URL, network passphrase, contract ID)
+ */
+export {};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/client.ts.html b/sdk/coverage/lcov-report/src/client.ts.html new file mode 100644 index 00000000..343080dc --- /dev/null +++ b/sdk/coverage/lcov-report/src/client.ts.html @@ -0,0 +1,847 @@ + + + + + + Code coverage report for src/client.ts + + + + + + + + + +
+
+

All files / src client.ts

+
+ +
+ 0% + Statements + 0/23 +
+ + +
+ 0% + Branches + 0/11 +
+ + +
+ 0% + Functions + 0/11 +
+ + +
+ 0% + Lines + 0/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * ILNClient — entry point for the Invoice Liquidity Network SDK.
+ *
+ * Provides factory methods for common environments so integrators can
+ * get started with a one-liner:
+ *
+ * ```ts
+ * import { ILNClient } from "@iln/sdk";
+ *
+ * const client = ILNClient.testnet(signer);
+ * const reputation = await client.getReputation("G...");
+ * ```
+ *
+ * ## Architecture
+ *
+ * `ILNClient` is a thin wrapper around the SDK's free functions. It holds
+ * the RPC server, network passphrase, contract address, and signer so
+ * every method call uses the same configuration automatically.
+ */
+ 
+import { SorobanRpc } from "@stellar/stellar-sdk";
+import type { ISigner } from "./signers/ISigner.js";
+ 
+// ---------------------------------------------------------------------------
+// Defaults
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Public Soroban RPC endpoint for Stellar Testnet.
+ */
+export const TESTNET_RPC_URL = "https://soroban-testnet.stellar.org";
+ 
+/**
+ * Public Soroban RPC endpoint for Stellar Mainnet (Pubnet).
+ */
+export const MAINNET_RPC_URL = "https://soroban.stellar.org";
+ 
+// ---------------------------------------------------------------------------
+// Configuration types
+// ---------------------------------------------------------------------------
+ 
+/** Full configuration for a custom ILNClient. */
+export interface ILNClientConfig {
+  /** Soroban RPC endpoint URL. */
+  rpcUrl: string;
+  /** Stellar network passphrase (e.g. `Networks.TESTNET`). */
+  networkPassphrase: string;
+  /** Deployed invoice-liquidity contract address. */
+  contractId: string;
+  /**
+   * Optional signer for methods that require authentication (e.g. fundInvoice).
+   * Read-only methods like getReputation work without a signer.
+   */
+  signer?: ISigner;
+}
+ 
+// ---------------------------------------------------------------------------
+// ILNClient
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Configured SDK client bound to a specific network and contract.
+ *
+ * @example
+ * ```ts
+ * // Testnet
+ * const client = ILNClient.testnet(mySigner);
+ *
+ * // Custom RPC (e.g. local validator node)
+ * const client = ILNClient.custom({
+ *   rpcUrl: "http://localhost:8000/soroban/rpc",
+ *   networkPassphrase: Networks.STANDALONE,
+ *   contractId: "CDEPLOYED...",
+ *   signer: mySigner,
+ * });
+ * ```
+ */
+export class ILNClient {
+  /** Soroban RPC server instance. */
+  readonly rpc: SorobanRpc.Server;
+  /** Stellar network passphrase. */
+  readonly networkPassphrase: string;
+  /** Deployed invoice-liquidity contract address. */
+  readonly contractId: string;
+  /** Optional signer for authenticated methods. */
+  readonly signer?: ISigner;
+ 
+  // Cached imports (lazy-loaded for tree-shaking)
+  private _getReputation?: typeof import("./methods/reputation.js").getReputation;
+  private _getContractStats?: typeof import("./methods/stats.js").getContractStats;
+ 
+  constructor(config: ILNClientConfig) {
+    this.rpc = new SorobanRpc.Server(config.rpcUrl);
+    this.networkPassphrase = config.networkPassphrase;
+    this.contractId = config.contractId;
+    this.signer = config.signer;
+  }
+ 
+  // --------------------------------------------------------------------------
+  // Factory methods
+  // --------------------------------------------------------------------------
+ 
+  /**
+   * Create a client pre-configured for Stellar Testnet.
+   *
+   * @param signer   - Optional signer for authenticated methods
+   * @param options  - Override defaults (rpcUrl, contractId)
+   *
+   * @example
+   * ```ts
+   * const client = ILNClient.testnet(freighterSigner);
+   * ```
+   */
+  static testnet(
+    signer?: ISigner,
+    options?: { rpcUrl?: string; contractId?: string }
+  ): ILNClient {
+    return new ILNClient({
+      rpcUrl: options?.rpcUrl ?? TESTNET_RPC_URL,
+      networkPassphrase: "Test SDF Network ; September 2015",
+      contractId:
+        options?.contractId ??
+        // Published testnet deployment: the canonical contract ID from
+        // the latest testnet CI/CD deployment. Update here when redeploying.
+        // TODO: replace with actual testnet contract ID once deployed
+        "CD2Q6M76VFLHNHDNROENMX7PJ5OBYBMVPM73S4M6XAJXN3NKCBJQPLUC",
+      signer,
+    });
+  }
+ 
+  /**
+   * Create a client pre-configured for Stellar Mainnet (Pubnet).
+   *
+   * @param signer   - Optional signer for authenticated methods
+   * @param options  - Override defaults (rpcUrl, contractId)
+   *
+   * @example
+   * ```ts
+   * const client = ILNClient.mainnet(freighterSigner);
+   * ```
+   */
+  static mainnet(
+    signer?: ISigner,
+    options?: { rpcUrl?: string; contractId?: string }
+  ): ILNClient {
+    // Future-proof: we allow configuring mainnet ahead of deployment
+    // so integrators can test their integration code against the API shape.
+    return new ILNClient({
+      rpcUrl: options?.rpcUrl ?? MAINNET_RPC_URL,
+      networkPassphrase: "Public Global Stellar Network ; September 2015",
+      contractId:
+        options?.contractId ??
+        // TODO: replace with actual mainnet contract ID after mainnet deployment
+        "",
+      signer,
+    });
+  }
+ 
+  /**
+   * Create a client with fully custom configuration.
+   *
+   * Use this for local development (standalone network), Futurenet, or
+   * private Stellar deployments.
+   *
+   * @param config - Full ILNClientConfig
+   */
+  static custom(config: ILNClientConfig): ILNClient {
+    return new ILNClient(config);
+  }
+ 
+  // --------------------------------------------------------------------------
+  // Methods
+  // --------------------------------------------------------------------------
+ 
+  /**
+   * Fetch the detailed reputation profile for an address.
+   *
+   * Read-only; does not require a signer.
+   *
+   * @param address - Stellar G… address to query
+   * @returns ReputationProfile (zeroed for unknown addresses)
+   */
+  async getReputation(
+    address: string
+  ): Promise<import("./methods/reputation.js").ReputationProfile> {
+    Iif (!this._getReputation) {
+      this._getReputation = (await import("./methods/reputation.js"))
+        .getReputation;
+    }
+    return this._getReputation(this.rpc, this.contractId, address, this.networkPassphrase);
+  }
+ 
+  /**
+   * Fetch protocol-wide statistics.
+   *
+   * Read-only; does not require a signer.
+   *
+   * @returns ContractStats
+   */
+  async getContractStats(): Promise<
+    import("./methods/stats.js").ContractStats
+  > {
+    Iif (!this._getContractStats) {
+      this._getContractStats = (await import("./methods/stats.js"))
+        .getContractStats;
+    }
+    return this._getContractStats(this.rpc, this.contractId, this.networkPassphrase);
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// Singleton
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Default ILNClient singleton.
+ *
+ * Must be initialised via `iln.configure(...)` before use.
+ *
+ * @example
+ * ```ts
+ * import { iln } from "@iln/sdk";
+ *
+ * iln.configure({ rpcUrl: "...", networkPassphrase: Networks.TESTNET, contractId: "..." });
+ * await iln.getReputation("G...");
+ * ```
+ */
+class ILNSingleton {
+  private _client: ILNClient | null = null;
+ 
+  configure(config: ILNClientConfig): void {
+    this._client = new ILNClient(config);
+  }
+ 
+  /** Access the underlying client. Throws if not configured. */
+  get client(): ILNClient {
+    Iif (!this._client) {
+      throw new Error(
+        "ILN singleton not configured. Call iln.configure({...}) first."
+      );
+    }
+    return this._client;
+  }
+ 
+  async getReputation(address: string) {
+    return this.client.getReputation(address);
+  }
+ 
+  async getContractStats() {
+    return this.client.getContractStats();
+  }
+}
+ 
+export const iln = new ILNSingleton();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/errors.ts.html b/sdk/coverage/lcov-report/src/errors.ts.html new file mode 100644 index 00000000..dbdf63c5 --- /dev/null +++ b/sdk/coverage/lcov-report/src/errors.ts.html @@ -0,0 +1,370 @@ + + + + + + Code coverage report for src/errors.ts + + + + + + + + + +
+
+

All files / src errors.ts

+
+ +
+ 0% + Statements + 0/126 +
+ + +
+ 0% + Branches + 0/78 +
+ + +
+ 0% + Functions + 0/42 +
+ + +
+ 0% + Lines + 0/86 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export class ILNError extends Error {
+  constructor(message: string, public readonly code?: number) {
+    super(message);
+    this.name = this.constructor.name;
+  }
+ 
+  static InvoiceNotFound = class extends ILNError { constructor(msg = "Invoice not found") { super(msg, 1); } };
+  static AlreadyFunded = class extends ILNError { constructor(msg = "Invoice already funded") { super(msg, 2); } };
+  static AlreadyPaid = class extends ILNError { constructor(msg = "Invoice already paid") { super(msg, 3); } };
+  static NotFunded = class extends ILNError { constructor(msg = "Invoice not funded") { super(msg, 4); } };
+  static Unauthorized = class extends ILNError { constructor(msg = "Unauthorized") { super(msg, 5); } };
+  static InvalidAmount = class extends ILNError { constructor(msg = "Invalid amount") { super(msg, 6); } };
+  static InvalidDiscountRate = class extends ILNError { constructor(msg = "Invalid discount rate") { super(msg, 7); } };
+  static InvalidDueDate = class extends ILNError { constructor(msg = "Invalid due date") { super(msg, 8); } };
+  static InvoiceDefaulted = class extends ILNError { constructor(msg = "Invoice defaulted") { super(msg, 9); } };
+  static NothingToClaim = class extends ILNError { constructor(msg = "Nothing to claim") { super(msg, 10); } };
+  static NotYetDefaulted = class extends ILNError { constructor(msg = "Not yet defaulted") { super(msg, 11); } };
+  static OverfundingRejected = class extends ILNError { constructor(msg = "Overfunding rejected") { super(msg, 12); } };
+  static InvoiceExpired = class extends ILNError { constructor(msg = "Invoice expired") { super(msg, 13); } };
+  static BatchTooLarge = class extends ILNError { constructor(msg = "Batch too large") { super(msg, 14); } };
+  static AlreadyCancelled = class extends ILNError { constructor(msg = "Already cancelled") { super(msg, 15); } };
+  static AlreadyInitialized = class extends ILNError { constructor(msg = "Already initialized") { super(msg, 16); } };
+  static AlreadyAppealed = class extends ILNError { constructor(msg = "Already appealed") { super(msg, 17); } };
+  static AppealWindowClosed = class extends ILNError { constructor(msg = "Appeal window closed") { super(msg, 18); } };
+  static NotDefaulted = class extends ILNError { constructor(msg = "Not defaulted") { super(msg, 19); } };
+  static AlreadyInQueue = class extends ILNError { constructor(msg = "Already in queue") { super(msg, 20); } };
+  static NotApprovedFunder = class extends ILNError { constructor(msg = "Not approved funder") { super(msg, 21); } };
+  static InvoiceAppealed = class extends ILNError { constructor(msg = "Invoice appealed") { super(msg, 22); } };
+  static AlreadyDisputed = class extends ILNError { constructor(msg = "Already disputed") { super(msg, 23); } };
+  static NotDisputed = class extends ILNError { constructor(msg = "Not disputed") { super(msg, 24); } };
+  static InvoiceDisputed = class extends ILNError { constructor(msg = "Invoice disputed") { super(msg, 25); } };
+  static ContractPaused = class extends ILNError { constructor(msg = "Contract paused") { super(msg, 26); } };
+  static DueDateTooSoon = class extends ILNError { constructor(msg = "Due date too soon") { super(msg, 27); } };
+  static DueDateTooFar = class extends ILNError { constructor(msg = "Due date too far") { super(msg, 28); } };
+  static SelfInvoice = class extends ILNError { constructor(msg = "Self invoice") { super(msg, 29); } };
+  static OverpaymentRejected = class extends ILNError { constructor(msg = "Overpayment rejected") { super(msg, 30); } };
+  static PayerReputationTooLow = class extends ILNError { constructor(msg = "Payer reputation too low") { super(msg, 31); } };
+  static ArithmeticOverflow = class extends ILNError { constructor(msg = "Arithmetic overflow") { super(msg, 32); } };
+  static FeeOnTransferToken = class extends ILNError { constructor(msg = "Fee on transfer token") { super(msg, 33); } };
+  static PayerUnverified = class extends ILNError { constructor(msg = "Payer unverified") { super(msg, 34); } };
+  static OracleDataStale = class extends ILNError { constructor(msg = "Oracle data stale") { super(msg, 35); } };
+  static AmountTooSmall = class extends ILNError { constructor(msg = "Amount too small") { super(msg, 36); } };
+  static InvoiceNotCancellable = class extends ILNError { constructor(msg = "Invoice not cancellable") { super(msg, 37); } };
+  static InvalidAddress = class extends ILNError { constructor(msg = "Invalid address") { super(msg, 38); } };
+  static InvalidTransfer = class extends ILNError { constructor(msg = "Invalid transfer") { super(msg, 39); } };
+  static InsufficientAmount = class extends ILNError { constructor(msg = "Insufficient amount") { super(msg, 999); } };
+ 
+  static fromError(error: any): Error {
+    const errorString = String(error);
+    const match = errorString.match(/Error\(Contract, (\d+)\)/);
+    Iif (match) {
+      const code = parseInt(match[1], 10);
+      switch (code) {
+        case 1: return new ILNError.InvoiceNotFound();
+        case 2: return new ILNError.AlreadyFunded();
+        case 3: return new ILNError.AlreadyPaid();
+        case 4: return new ILNError.NotFunded();
+        case 5: return new ILNError.Unauthorized();
+        case 6: return new ILNError.InvalidAmount();
+        case 7: return new ILNError.InvalidDiscountRate();
+        case 8: return new ILNError.InvalidDueDate();
+        case 9: return new ILNError.InvoiceDefaulted();
+        case 10: return new ILNError.NothingToClaim();
+        case 11: return new ILNError.NotYetDefaulted();
+        case 12: return new ILNError.OverfundingRejected();
+        case 13: return new ILNError.InvoiceExpired();
+        case 14: return new ILNError.BatchTooLarge();
+        case 15: return new ILNError.AlreadyCancelled();
+        case 16: return new ILNError.AlreadyInitialized();
+        case 17: return new ILNError.AlreadyAppealed();
+        case 18: return new ILNError.AppealWindowClosed();
+        case 19: return new ILNError.NotDefaulted();
+        case 20: return new ILNError.AlreadyInQueue();
+        case 21: return new ILNError.NotApprovedFunder();
+        case 22: return new ILNError.InvoiceAppealed();
+        case 23: return new ILNError.AlreadyDisputed();
+        case 24: return new ILNError.NotDisputed();
+        case 25: return new ILNError.InvoiceDisputed();
+        case 26: return new ILNError.ContractPaused();
+        case 27: return new ILNError.DueDateTooSoon();
+        case 28: return new ILNError.DueDateTooFar();
+        case 29: return new ILNError.SelfInvoice();
+        case 30: return new ILNError.OverpaymentRejected();
+        case 31: return new ILNError.PayerReputationTooLow();
+        case 32: return new ILNError.ArithmeticOverflow();
+        case 33: return new ILNError.FeeOnTransferToken();
+        case 34: return new ILNError.PayerUnverified();
+        case 35: return new ILNError.OracleDataStale();
+        case 36: return new ILNError.AmountTooSmall();
+        case 37: return new ILNError.InvoiceNotCancellable();
+      }
+    }
+    return new Error(errorString);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/events/index.html b/sdk/coverage/lcov-report/src/events/index.html new file mode 100644 index 00000000..659b79f6 --- /dev/null +++ b/sdk/coverage/lcov-report/src/events/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/events + + + + + + + + + +
+
+

All files src/events

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
subscribe.d.ts +
+
0%0/00%0/00%0/00%0/0
types.d.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/events/subscribe.d.ts.html b/sdk/coverage/lcov-report/src/events/subscribe.d.ts.html new file mode 100644 index 00000000..02b9c7fa --- /dev/null +++ b/sdk/coverage/lcov-report/src/events/subscribe.d.ts.html @@ -0,0 +1,262 @@ + + + + + + Code coverage report for src/events/subscribe.d.ts + + + + + + + + + +
+
+

All files / src/events subscribe.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Real-time ILN contract event subscription backed by Horizon's SSE
+ * `/effects` + `/contract-events` streaming endpoint.
+ *
+ * Features
+ * --------
+ * - Typed discriminated-union events (ILNEvent)
+ * - Client-side filtering by event type, invoiceId, and address
+ * - Transparent reconnection with exponential back-off on stream errors
+ * - Clean `Unsubscribe` tear-down function returned to the caller
+ */
+import { Server as HorizonServer } from "@stellar/stellar-sdk/lib/horizon/index.js";
+import type { EventFilter, ILNEvent, Unsubscribe } from "./types.js";
+interface HorizonContractEvent {
+    type: string;
+    /** Array of base-64 XDR ScVal strings representing the topics. */
+    topic: string[];
+    /** Base-64 XDR ScVal string for the event body / value. */
+    value: string;
+    contractId?: string;
+    ledger?: number;
+    ledgerClosedAt?: string;
+    txHash?: string;
+    id?: string;
+}
+/**
+ * Parse a raw Horizon contract-event record into a typed ILNEvent.
+ *
+ * Returns `null` when the event cannot be decoded or is not a known ILN type.
+ */
+export declare function parseContractEvent(raw: HorizonContractEvent): ILNEvent | null;
+/**
+ * Returns true when the parsed event satisfies the caller's EventFilter.
+ */
+export declare function matchesFilter(event: ILNEvent, filter: EventFilter): boolean;
+/**
+ * Subscribe to real-time ILN contract events via Horizon's SSE stream.
+ *
+ * Handles stream disconnection with exponential back-off (500 ms → 30 s).
+ * The returned `Unsubscribe` function closes the stream and cancels any
+ * pending reconnection timer.
+ *
+ * @param horizon         - Horizon server instance (use `new Server(horizonUrl)`)
+ * @param contractId      - Deployed invoice-liquidity contract address
+ * @param filter          - Optional criteria; empty object matches all events
+ * @param handler         - Called once per matching decoded event
+ * @param onError         - Optional error callback for logging / monitoring
+ * @returns Unsubscribe   - Call to stop the stream
+ *
+ * @example
+ * ```ts
+ * const unsub = subscribe(horizon, CONTRACT_ID, { types: ["funded", "paid"] },
+ *   (event) => console.log(event));
+ * // later…
+ * unsub();
+ * ```
+ */
+export declare function subscribe(horizon: HorizonServer, contractId: string, filter: EventFilter, handler: (event: ILNEvent) => void, onError?: (err: unknown) => void): Unsubscribe;
+export {};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/events/types.d.ts.html b/sdk/coverage/lcov-report/src/events/types.d.ts.html new file mode 100644 index 00000000..0ae62bcb --- /dev/null +++ b/sdk/coverage/lcov-report/src/events/types.d.ts.html @@ -0,0 +1,622 @@ + + + + + + Code coverage report for src/events/types.d.ts + + + + + + + + + +
+
+

All files / src/events types.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Typed event union for the Invoice Liquidity Network contract.
+ *
+ * Every event emitted on-chain has a `type` discriminant that matches the
+ * Soroban contract-event topic string, plus the decoded data fields.
+ */
+export type ILNEventType = "submitted" | "funded" | "paid" | "partially_paid" | "defaulted" | "appealed" | "appeal_resolved" | "disputed" | "dispute_resolved" | "token_added" | "token_removed" | "parameter_updated" | "transferred" | "cancelled" | "paused" | "unpaused" | "upgraded" | "admin_changed" | "fund_requested" | "fund_queue_resolved";
+export interface InvoiceSubmittedEvent {
+    type: "submitted";
+    invoiceId: bigint;
+    freelancer: string;
+    payer: string;
+    token: string;
+    amount: bigint;
+    dueDate: bigint;
+    discountRate: number;
+    status: string;
+    timestamp: bigint;
+}
+export interface InvoiceFundedEvent {
+    type: "funded";
+    invoiceId: bigint;
+    funder: string;
+    freelancer: string;
+    payer: string;
+    token: string;
+    fundAmount: bigint;
+    amountFunded: bigint;
+    invoiceAmount: bigint;
+    dueDate: bigint;
+    discountRate: number;
+    fundedAt: bigint | null;
+    status: string;
+    lp: string;
+    effectiveYieldBps: number;
+    timestamp: bigint;
+}
+export interface InvoicePaidEvent {
+    type: "paid";
+    invoiceId: bigint;
+    payer: string;
+    lp: string;
+    freelancer: string;
+    token: string;
+    amountPaid: bigint;
+    lpEarned: bigint;
+    lpPayout: bigint;
+    settlementTimestamp: bigint;
+    paidOnTime: boolean;
+    status: string;
+}
+export interface InvoicePartiallyPaidEvent {
+    type: "partially_paid";
+    invoiceId: bigint;
+    payer: string;
+    amountPaidNow: bigint;
+    totalAmountPaid: bigint;
+    remainingAmount: bigint;
+}
+export interface InvoiceDefaultedEvent {
+    type: "defaulted";
+    invoiceId: bigint;
+    funder: string;
+    freelancer: string;
+    payer: string;
+    token: string;
+    amount: bigint;
+    dueDate: bigint;
+    defaultedAt: bigint;
+    discountAmount: bigint;
+    status: string;
+}
+export interface DefaultAppealedEvent {
+    type: "appealed";
+    invoiceId: bigint;
+    payer: string;
+    evidenceHash: string;
+    appealedAt: bigint;
+}
+export interface AppealResolvedEvent {
+    type: "appeal_resolved";
+    invoiceId: bigint;
+    payer: string;
+    upheld: boolean;
+    resolvedAt: bigint;
+}
+export interface InvoiceDisputedEvent {
+    type: "disputed";
+    invoiceId: bigint;
+    payer: string;
+    reasonHash: string;
+    disputedAt: bigint;
+}
+export interface DisputeResolvedEvent {
+    type: "dispute_resolved";
+    invoiceId: bigint;
+    resolutionHash: string;
+    resolution: number;
+    resolvedAt: bigint;
+}
+export interface TokenAddedEvent {
+    type: "token_added";
+    token: string;
+    decimals: number;
+}
+export interface TokenRemovedEvent {
+    type: "token_removed";
+    token: string;
+}
+export interface ParameterUpdatedEvent {
+    type: "parameter_updated";
+    paramName: string;
+    oldValue: bigint;
+    newValue: bigint;
+    updatedBy: string;
+}
+export interface InvoiceTransferredEvent {
+    type: "transferred";
+    invoiceId: bigint;
+    oldFreelancer: string;
+    newFreelancer: string;
+    status: string;
+}
+export interface InvoiceCancelledEvent {
+    type: "cancelled";
+    invoiceId: bigint;
+    freelancer: string;
+    status: string;
+}
+export interface ContractPausedEvent {
+    type: "paused";
+    timestamp: bigint;
+}
+export interface ContractUnpausedEvent {
+    type: "unpaused";
+    timestamp: bigint;
+}
+export interface ContractUpgradedEvent {
+    type: "upgraded";
+    admin: string;
+    newWasmHash: string;
+    timestamp: bigint;
+}
+export interface AdminChangedEvent {
+    type: "admin_changed";
+    oldAdmin: string;
+    newAdmin: string;
+    timestamp: bigint;
+}
+export interface FundRequestedEvent {
+    type: "fund_requested";
+    invoiceId: bigint;
+    lp: string;
+    score: number;
+}
+export interface FundQueueResolvedEvent {
+    type: "fund_queue_resolved";
+    invoiceId: bigint;
+    approvedLp: string;
+    score: number;
+}
+export type ILNEvent = InvoiceSubmittedEvent | InvoiceFundedEvent | InvoicePaidEvent | InvoicePartiallyPaidEvent | InvoiceDefaultedEvent | DefaultAppealedEvent | AppealResolvedEvent | InvoiceDisputedEvent | DisputeResolvedEvent | TokenAddedEvent | TokenRemovedEvent | ParameterUpdatedEvent | InvoiceTransferredEvent | InvoiceCancelledEvent | ContractPausedEvent | ContractUnpausedEvent | ContractUpgradedEvent | AdminChangedEvent | FundRequestedEvent | FundQueueResolvedEvent;
+/**
+ * Criteria used to narrow the event stream.  All fields are optional; an
+ * empty filter matches every ILN contract event.
+ */
+export interface EventFilter {
+    /** Only emit events whose `type` is in this list. */
+    types?: ILNEventType[];
+    /** Only emit events that mention this invoice ID (in a topic). */
+    invoiceId?: bigint;
+    /**
+     * Only emit events that mention this Stellar address in any topic
+     * (freelancer, payer, LP, admin, token …).
+     */
+    address?: string;
+}
+/** Call to stop the subscription and close the underlying stream. */
+export type Unsubscribe = () => void;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/index.d.ts.html b/sdk/coverage/lcov-report/src/index.d.ts.html new file mode 100644 index 00000000..6a07c72a --- /dev/null +++ b/sdk/coverage/lcov-report/src/index.d.ts.html @@ -0,0 +1,172 @@ + + + + + + Code coverage report for src/index.d.ts + + + + + + + + + +
+
+

All files / src index.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * @iln/sdk — Invoice Liquidity Network TypeScript SDK
+ *
+ * Public surface area re-exported from this entry point.
+ */
+export { fundInvoice, computeEffectiveYieldBps } from "./methods/fundInvoice.js";
+export { getReputation } from "./methods/reputation.js";
+export { getContractStats } from "./methods/stats.js";
+export { getAllowance, buildApproveTransaction, isAllowanceSufficient, } from "./utils/allowance.js";
+export { validateGAddress, validateContractId, validateAmount, validateDiscountRate, validateDueDate, } from "./utils/validate.js";
+export { KeypairSigner } from "./signers/KeypairSigner.js";
+export { FreighterSigner, ILNError, ILNErrorCode } from "./signers/FreighterSigner.js";
+export { subscribe, parseContractEvent, matchesFilter } from "./events/subscribe.js";
+export { ILNClient, iln } from "./client.js";
+export type { ISigner } from "./signers/ISigner.js";
+export type { ILNClientConfig } from "./client.js";
+export type { ReputationProfile } from "./methods/reputation.js";
+export type { ContractStats } from "./methods/stats.js";
+export type { FundOptions, FundResult, InvoiceView, AllowanceParams, AllowanceResult, } from "./types.js";
+export type { ILNEvent, ILNEventType, EventFilter, Unsubscribe, } from "./events/types.js";
+export { getInvoice, listInvoicesBySubmitter, listInvoicesByLP } from "./methods/queries.js";
+export { submitInvoice } from "./methods/submitInvoice.js";
+export { transferLPPosition } from "./methods/transferLPPosition.js";
+export { cancelInvoice } from "./methods/cancelInvoice.js";
+export { markPaid } from "./methods/markPaid.js";
+export { createProposal, castVote, executeProposal, getProposal, listProposals, } from "./methods/governance.js";
+export { ProposalAction, ProposalStatus, } from "./types/governance.js";
+export type { Proposal, ProposalFilter, CreateProposalResult, } from "./types/governance.js";
+export { ILNError } from "./errors.js";
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/index.html b/sdk/coverage/lcov-report/src/index.html new file mode 100644 index 00000000..b59414b9 --- /dev/null +++ b/sdk/coverage/lcov-report/src/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 0% + Statements + 0/149 +
+ + +
+ 0% + Branches + 0/89 +
+ + +
+ 0% + Functions + 0/53 +
+ + +
+ 0% + Lines + 0/109 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
client.d.ts +
+
0%0/00%0/00%0/00%0/0
client.test.d.ts +
+
0%0/00%0/00%0/00%0/0
client.ts +
+
0%0/230%0/110%0/110%0/23
errors.ts +
+
0%0/1260%0/780%0/420%0/86
index.d.ts +
+
0%0/00%0/00%0/00%0/0
types.d.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/cancelInvoice.d.ts.html b/sdk/coverage/lcov-report/src/methods/cancelInvoice.d.ts.html new file mode 100644 index 00000000..6f180694 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/cancelInvoice.d.ts.html @@ -0,0 +1,151 @@ + + + + + + Code coverage report for src/methods/cancelInvoice.d.ts + + + + + + + + + +
+
+

All files / src/methods cancelInvoice.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { SorobanRpc, Account, Transaction } from "@stellar/stellar-sdk";
+/**
+ * Cancel a pending invoice.
+ * @param server Soroban RPC server
+ * @param contractAddress Contract address
+ * @param invoiceId The ID of the invoice to cancel
+ * @param sourceAccount The account of the freelancer/submitter
+ * @param signTransaction A function to sign the transaction (e.g. Freighter or Keypair)
+ * @param networkPassphrase The network passphrase
+ * @returns Object containing txHash
+ * @throws {ILNError.InvoiceNotCancellable} When the invoice is not in a Pending state
+ * @throws {ILNError.Unauthorized} When caller is not the invoice submitter
+ * @throws {ILNError} When simulation or execution fails
+ * @example
+ * ```ts
+ * const { txHash } = await cancelInvoice(server, contractAddress, 42n, sourceAccount, signTx, Networks.TESTNET);
+ * console.log(txHash);
+ * ```
+ */
+export declare function cancelInvoice(server: SorobanRpc.Server, contractAddress: string, invoiceId: bigint, sourceAccount: Account, signTransaction: (tx: Transaction) => Promise<Transaction> | Transaction, networkPassphrase: string): Promise<{
+    txHash: string;
+}>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/fundInvoice.d.ts.html b/sdk/coverage/lcov-report/src/methods/fundInvoice.d.ts.html new file mode 100644 index 00000000..36612e27 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/fundInvoice.d.ts.html @@ -0,0 +1,283 @@ + + + + + + Code coverage report for src/methods/fundInvoice.d.ts + + + + + + + + + +
+
+

All files / src/methods fundInvoice.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * fundInvoice — LP-facing SDK method for the Invoice Liquidity Network.
+ *
+ * Handles the full two-step allowance + funding flow automatically:
+ *   1. Fetch the invoice to determine the token and amount required.
+ *   2. Query the LP's current token allowance for the contract.
+ *   3. If insufficient, build, sign and submit an `approve` transaction.
+ *   4. Build, sign and submit the `fund_invoice` contract call.
+ *   5. Return `{ txHash, effectiveYieldBps }`.
+ *
+ * Progress is surfaced via optional callbacks on FundOptions so integrators
+ * can update UI without polling.
+ */
+import { SorobanRpc, Keypair } from "@stellar/stellar-sdk";
+import type { FundOptions, FundResult } from "../types.js";
+/**
+ * Compute the annualised effective yield in basis points for an LP position.
+ *
+ *   effectiveYieldBps = discountRate × daysToMaturity / 365
+ *
+ * Returns `0` when the due date is already in the past.
+ *
+ * @param discountRateBps - Invoice discount rate in basis points (e.g. 300 = 3%)
+ * @param dueDateUnix     - Invoice due date as Unix timestamp (seconds)
+ * @param nowUnix         - Current time as Unix timestamp; defaults to Date.now()
+ */
+export declare function computeEffectiveYieldBps(discountRateBps: number, dueDateUnix: number, nowUnix?: number): number;
+/**
+ * Fund an invoice as a liquidity provider.
+ *
+ * Automatically manages the token allowance before calling `fund_invoice`
+ * on-chain. When an `approve` transaction is needed, `onApprovalRequired`
+ * fires first (so the UI can show a prompt), and `onApprovalSent` fires
+ * after the approval is submitted. `onFunded` fires once the fund transaction
+ * is sent.
+ *
+ * @param server              - Soroban RPC server connected to the target network
+ * @param contractAddress     - Deployed invoice-liquidity contract address
+ * @param lpKeypair           - Keypair of the liquidity provider (signs all txs)
+ * @param invoiceId           - ID of the invoice to fund
+ * @param options             - Optional configuration and progress callbacks:
+ *   - `requireOracleVerification` — reject if the contract has no price oracle
+ *   - `onApprovalRequired`        — fired before the approve tx is built
+ *   - `onApprovalSent`            — fired after the approve tx is submitted
+ *   - `onFunded`                  — fired after the fund tx is submitted
+ * @param networkPassphrase   - Stellar network passphrase (default: TESTNET)
+ *
+ * @returns `{ txHash, effectiveYieldBps }` on success
+ *
+ * @throws When the invoice is not fundable (wrong status, not found, etc.)
+ * @throws When the approve or fund transaction is rejected by the network
+ * @throws When oracle verification is required but fails
+ *
+ * @example
+ * ```ts
+ * const result = await fundInvoice(server, CONTRACT_ID, lpKeypair, 42n, {
+ *   onApprovalRequired: ({ requiredAmount, currentAllowance }) =>
+ *     console.log(`Need to approve ${requiredAmount}, have ${currentAllowance}`),
+ *   onApprovalSent: ({ approveTxHash }) =>
+ *     console.log(`Approval submitted: ${approveTxHash}`),
+ *   onFunded: ({ effectiveYieldBps, invoiceId }) =>
+ *     console.log(`Invoice ${invoiceId} funded! Yield: ${effectiveYieldBps} bps`),
+ * });
+ * ```
+ */
+export declare function fundInvoice(server: SorobanRpc.Server, contractAddress: string, lpKeypair: Keypair, invoiceId: bigint, options?: FundOptions, networkPassphrase?: string): Promise<FundResult>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/governance.d.ts.html b/sdk/coverage/lcov-report/src/methods/governance.d.ts.html new file mode 100644 index 00000000..4c1a92a3 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/governance.d.ts.html @@ -0,0 +1,202 @@ + + + + + + Code coverage report for src/methods/governance.d.ts + + + + + + + + + +
+
+

All files / src/methods governance.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { SorobanRpc, Account, Transaction } from "@stellar/stellar-sdk";
+import { ProposalAction, type Proposal, type ProposalFilter, type CreateProposalResult } from "../types/governance.js";
+/**
+ * Create a new governance proposal.
+ *
+ * @param server Soroban RPC server
+ * @param contractAddress Governance contract address
+ * @param action The parameter-changing action to propose
+ * @param proposedValue The proposed new value for the action's parameter
+ * @param descriptionHash Hex-encoded 32-byte hash of the off-chain description
+ * @param sourceAccount The proposer's account
+ * @param signTransaction A function to sign the transaction
+ * @param networkPassphrase The network passphrase
+ * @returns The new proposalId and txHash
+ * @throws {ILNError} When simulation or execution fails
+ */
+export declare function createProposal(server: SorobanRpc.Server, contractAddress: string, action: ProposalAction, proposedValue: bigint, descriptionHash: string, sourceAccount: Account, signTransaction: (tx: Transaction) => Promise<Transaction> | Transaction, networkPassphrase: string): Promise<CreateProposalResult>;
+/**
+ * Cast a vote on an active proposal.
+ *
+ * @param support `true` to vote for, `false` to vote against.
+ */
+export declare function castVote(server: SorobanRpc.Server, contractAddress: string, proposalId: bigint, support: boolean, sourceAccount: Account, signTransaction: (tx: Transaction) => Promise<Transaction> | Transaction, networkPassphrase: string): Promise<{
+    txHash: string;
+}>;
+/**
+ * Execute a proposal that has passed its vote.
+ */
+export declare function executeProposal(server: SorobanRpc.Server, contractAddress: string, proposalId: bigint, sourceAccount: Account, signTransaction: (tx: Transaction) => Promise<Transaction> | Transaction, networkPassphrase: string): Promise<{
+    txHash: string;
+}>;
+/**
+ * Fetch a single proposal by ID (read-only; no signer required).
+ */
+export declare function getProposal(server: SorobanRpc.Server, contractAddress: string, id: bigint, sourceAccount: Account, networkPassphrase: string): Promise<Proposal>;
+/**
+ * List proposals, optionally filtered by status and/or proposer (read-only).
+ */
+export declare function listProposals(server: SorobanRpc.Server, contractAddress: string, sourceAccount: Account, networkPassphrase: string, filter?: ProposalFilter): Promise<Proposal[]>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/index.html b/sdk/coverage/lcov-report/src/methods/index.html new file mode 100644 index 00000000..b50e8415 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/index.html @@ -0,0 +1,281 @@ + + + + + + Code coverage report for src/methods + + + + + + + + + +
+
+

All files src/methods

+
+ +
+ 0% + Statements + 0/71 +
+ + +
+ 0% + Branches + 0/69 +
+ + +
+ 0% + Functions + 0/8 +
+ + +
+ 0% + Lines + 0/71 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
cancelInvoice.d.ts +
+
0%0/00%0/00%0/00%0/0
fundInvoice.d.ts +
+
0%0/00%0/00%0/00%0/0
governance.d.ts +
+
0%0/00%0/00%0/00%0/0
markPaid.d.ts +
+
0%0/00%0/00%0/00%0/0
queries.d.ts +
+
0%0/00%0/00%0/00%0/0
queries.ts +
+
0%0/400%0/370%0/50%0/40
reputation.d.ts +
+
0%0/00%0/00%0/00%0/0
reputation.ts +
+
0%0/150%0/140%0/20%0/15
stats.d.ts +
+
0%0/00%0/00%0/00%0/0
stats.ts +
+
0%0/160%0/180%0/10%0/16
submitInvoice.d.ts +
+
0%0/00%0/00%0/00%0/0
transferLPPosition.d.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/markPaid.d.ts.html b/sdk/coverage/lcov-report/src/methods/markPaid.d.ts.html new file mode 100644 index 00000000..eab44775 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/markPaid.d.ts.html @@ -0,0 +1,148 @@ + + + + + + Code coverage report for src/methods/markPaid.d.ts + + + + + + + + + +
+
+

All files / src/methods markPaid.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { SorobanRpc, Account, Transaction } from "@stellar/stellar-sdk";
+import type { MarkPaidResult } from "../types/params.js";
+/**
+ * Mark an invoice as paid (supports partial payments).
+ * @param server Soroban RPC server
+ * @param contractAddress Contract address
+ * @param invoiceId The invoice ID
+ * @param amount Optional amount to pay. If omitted, pays the full remaining balance.
+ * @param sourceAccount The account of the payer
+ * @param signTransaction A function to sign the transaction
+ * @param networkPassphrase The network passphrase
+ * @returns Object with txHash, remainingBalance and fullySettled flag
+ * @throws {ILNError.InsufficientAmount} If payment amount is <= 0 or exceeds outstanding balance
+ * @throws {ILNError} When simulation or execution fails
+ * @example
+ * ```ts
+ * const result = await markPaid(server, contractAddress, 42n, 100n, sourceAccount, signTx, Networks.TESTNET);
+ * console.log(`Remaining balance: ${result.remainingBalance}`);
+ * ```
+ */
+export declare function markPaid(server: SorobanRpc.Server, contractAddress: string, invoiceId: bigint, amount: bigint | undefined, sourceAccount: Account, signTransaction: (tx: Transaction) => Promise<Transaction> | Transaction, networkPassphrase: string): Promise<MarkPaidResult>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/queries.d.ts.html b/sdk/coverage/lcov-report/src/methods/queries.d.ts.html new file mode 100644 index 00000000..3c7480fc --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/queries.d.ts.html @@ -0,0 +1,244 @@ + + + + + + Code coverage report for src/methods/queries.d.ts + + + + + + + + + +
+
+

All files / src/methods queries.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { SorobanRpc, Account } from "@stellar/stellar-sdk";
+import type { Invoice } from "../types/invoice.js";
+/**
+ * Fetch a single invoice by its ID.
+ * @param server Soroban RPC server instance
+ * @param contractAddress The contract's address
+ * @param invoiceId The invoice ID
+ * @param sourceAccount Account used for simulation (does not consume sequence or fees)
+ * @param networkPassphrase The network passphrase
+ * @returns The invoice data including computed yield
+ * @throws {ILNError.InvoiceNotFound} If the invoice does not exist
+ * @throws {ILNError} On other simulation errors
+ * @example
+ * ```ts
+ * const invoice = await getInvoice(server, contractAddress, 42n, sourceAccount, Networks.TESTNET);
+ * console.log(`Invoice status: ${invoice.status}`);
+ * ```
+ */
+export declare function getInvoice(server: SorobanRpc.Server, contractAddress: string, invoiceId: bigint, sourceAccount: Account, networkPassphrase: string): Promise<Invoice>;
+/**
+ * List invoices submitted by a specific freelancer address.
+ * @param server Soroban RPC server instance
+ * @param contractAddress The contract's address
+ * @param submitter The freelancer's address
+ * @param sourceAccount Account used for simulation
+ * @param networkPassphrase The network passphrase
+ * @param page The page number (0-indexed)
+ * @param pageSize The number of items per page
+ * @returns Array of invoices
+ * @throws {ILNError} On simulation errors
+ * @example
+ * ```ts
+ * const invoices = await listInvoicesBySubmitter(server, contractAddress, "G...", sourceAccount, Networks.TESTNET, 0, 10);
+ * ```
+ */
+export declare function listInvoicesBySubmitter(server: SorobanRpc.Server, contractAddress: string, submitter: string, sourceAccount: Account, networkPassphrase: string, page?: number, pageSize?: number): Promise<Invoice[]>;
+/**
+ * List invoices funded by a specific LP address.
+ * @param server Soroban RPC server instance
+ * @param contractAddress The contract's address
+ * @param lp The liquidity provider's address
+ * @param sourceAccount Account used for simulation
+ * @param networkPassphrase The network passphrase
+ * @param page The page number (0-indexed)
+ * @param pageSize The number of items per page
+ * @returns Array of invoices
+ * @throws {ILNError} On simulation errors
+ * @example
+ * ```ts
+ * const invoices = await listInvoicesByLP(server, contractAddress, "G...", sourceAccount, Networks.TESTNET, 0, 10);
+ * ```
+ */
+export declare function listInvoicesByLP(server: SorobanRpc.Server, contractAddress: string, lp: string, sourceAccount: Account, networkPassphrase: string, page?: number, pageSize?: number): Promise<Invoice[]>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/queries.ts.html b/sdk/coverage/lcov-report/src/methods/queries.ts.html new file mode 100644 index 00000000..0e03deb9 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/queries.ts.html @@ -0,0 +1,781 @@ + + + + + + Code coverage report for src/methods/queries.ts + + + + + + + + + +
+
+

All files / src/methods queries.ts

+
+ +
+ 0% + Statements + 0/40 +
+ + +
+ 0% + Branches + 0/37 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 0% + Lines + 0/40 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {
+  Contract,
+  SorobanRpc,
+  TransactionBuilder,
+  BASE_FEE,
+  scValToNative,
+  nativeToScVal,
+  Account,
+} from "@stellar/stellar-sdk";
+import type { Invoice } from "../types/invoice.js";
+import { ILNError } from "../errors.js";
+import { computeEffectiveYieldBps } from "./fundInvoice.js";
+ 
+/**
+ * Fetch a single invoice by its ID.
+ * @param server Soroban RPC server instance
+ * @param contractAddress The contract's address
+ * @param invoiceId The invoice ID
+ * @param sourceAccount Account used for simulation (does not consume sequence or fees)
+ * @param networkPassphrase The network passphrase
+ * @returns The invoice data including computed yield
+ * @throws {ILNError.InvoiceNotFound} If the invoice does not exist
+ * @throws {ILNError} On other simulation errors
+ * @example
+ * ```ts
+ * const invoice = await getInvoice(server, contractAddress, 42n, sourceAccount, Networks.TESTNET);
+ * console.log(`Invoice status: ${invoice.status}`);
+ * ```
+ */
+export async function getInvoice(
+  server: SorobanRpc.Server,
+  contractAddress: string,
+  invoiceId: bigint,
+  sourceAccount: Account,
+  networkPassphrase: string
+): Promise<Invoice> {
+  const contract = new Contract(contractAddress);
+  const op = contract.call(
+    "get_invoice",
+    nativeToScVal(invoiceId, { type: "u64" })
+  );
+ 
+  const tx = new TransactionBuilder(sourceAccount, {
+    fee: BASE_FEE,
+    networkPassphrase,
+  })
+    .addOperation(op)
+    .setTimeout(30)
+    .build();
+ 
+  const sim = await server.simulateTransaction(tx);
+ 
+  Iif (SorobanRpc.Api.isSimulationError(sim)) {
+    Iif (String(sim.error).includes("NotFound") || String(sim.error).includes("Error(Contract, 1)")) {
+      throw new ILNError.InvoiceNotFound(`Invoice ${invoiceId} not found`);
+    }
+    throw ILNError.fromError(sim.error);
+  }
+  Iif (!sim.result?.retval) {
+    throw new ILNError.InvoiceNotFound(`Invoice ${invoiceId} not found`);
+  }
+ 
+  const raw = scValToNative(sim.result.retval) as Record<string, unknown>;
+  const dueDate = Number(raw["due_date"]);
+  const discountRate = Number(raw["discount_rate"]);
+ 
+  return {
+    id: BigInt(String(raw["id"])),
+    freelancer: String(raw["freelancer"]),
+    payer: String(raw["payer"]),
+    token: String(raw["token"]),
+    amount: BigInt(String(raw["amount"])),
+    dueDate,
+    discountRate,
+    status: (raw["status"] as any)?.tag || String(raw["status"]) as any, // handle scval enum
+    funder: raw["funder"] ? String(raw["funder"]) : undefined,
+    fundedAt: raw["funded_at"] ? Number(raw["funded_at"]) : undefined,
+    amountFunded: BigInt(String(raw["amount_funded"])),
+    amountPaid: BigInt(String(raw["amount_paid"])),
+    referralCode: raw["referral_code"] ? Buffer.from(raw["referral_code"] as any).toString('hex') : undefined,
+    submitterReputation: Number(raw["submitter_reputation"]),
+    effectiveYieldBps: computeEffectiveYieldBps(discountRate, dueDate),
+  };
+}
+ 
+/**
+ * List invoices submitted by a specific freelancer address.
+ * @param server Soroban RPC server instance
+ * @param contractAddress The contract's address
+ * @param submitter The freelancer's address
+ * @param sourceAccount Account used for simulation
+ * @param networkPassphrase The network passphrase
+ * @param page The page number (0-indexed)
+ * @param pageSize The number of items per page
+ * @returns Array of invoices
+ * @throws {ILNError} On simulation errors
+ * @example
+ * ```ts
+ * const invoices = await listInvoicesBySubmitter(server, contractAddress, "G...", sourceAccount, Networks.TESTNET, 0, 10);
+ * ```
+ */
+export async function listInvoicesBySubmitter(
+  server: SorobanRpc.Server,
+  contractAddress: string,
+  submitter: string,
+  sourceAccount: Account,
+  networkPassphrase: string,
+  page: number = 0,
+  pageSize: number = 50
+): Promise<Invoice[]> {
+  const contract = new Contract(contractAddress);
+  const op = contract.call(
+    "list_invoices_by_submitter",
+    nativeToScVal(submitter, { type: "address" }),
+    nativeToScVal(page, { type: "u32" }),
+    nativeToScVal(pageSize, { type: "u32" })
+  );
+ 
+  const tx = new TransactionBuilder(sourceAccount, {
+    fee: BASE_FEE,
+    networkPassphrase,
+  })
+    .addOperation(op)
+    .setTimeout(30)
+    .build();
+ 
+  const sim = await server.simulateTransaction(tx);
+ 
+  Iif (SorobanRpc.Api.isSimulationError(sim)) {
+    throw ILNError.fromError(sim.error);
+  }
+  Iif (!sim.result?.retval) {
+    return [];
+  }
+ 
+  const rawArr = scValToNative(sim.result.retval) as Record<string, unknown>[];
+  return rawArr.map(raw => {
+    const dueDate = Number(raw["due_date"]);
+    const discountRate = Number(raw["discount_rate"]);
+    return {
+      id: BigInt(String(raw["id"])),
+      freelancer: String(raw["freelancer"]),
+      payer: String(raw["payer"]),
+      token: String(raw["token"]),
+      amount: BigInt(String(raw["amount"])),
+      dueDate,
+      discountRate,
+      status: (raw["status"] as any)?.tag || String(raw["status"]) as any,
+      funder: raw["funder"] ? String(raw["funder"]) : undefined,
+      fundedAt: raw["funded_at"] ? Number(raw["funded_at"]) : undefined,
+      amountFunded: BigInt(String(raw["amount_funded"])),
+      amountPaid: BigInt(String(raw["amount_paid"])),
+      referralCode: raw["referral_code"] ? Buffer.from(raw["referral_code"] as any).toString('hex') : undefined,
+      submitterReputation: Number(raw["submitter_reputation"]),
+      effectiveYieldBps: computeEffectiveYieldBps(discountRate, dueDate),
+    };
+  });
+}
+ 
+/**
+ * List invoices funded by a specific LP address.
+ * @param server Soroban RPC server instance
+ * @param contractAddress The contract's address
+ * @param lp The liquidity provider's address
+ * @param sourceAccount Account used for simulation
+ * @param networkPassphrase The network passphrase
+ * @param page The page number (0-indexed)
+ * @param pageSize The number of items per page
+ * @returns Array of invoices
+ * @throws {ILNError} On simulation errors
+ * @example
+ * ```ts
+ * const invoices = await listInvoicesByLP(server, contractAddress, "G...", sourceAccount, Networks.TESTNET, 0, 10);
+ * ```
+ */
+export async function listInvoicesByLP(
+  server: SorobanRpc.Server,
+  contractAddress: string,
+  lp: string,
+  sourceAccount: Account,
+  networkPassphrase: string,
+  page: number = 0,
+  pageSize: number = 50
+): Promise<Invoice[]> {
+  const contract = new Contract(contractAddress);
+  const op = contract.call(
+    "list_invoices_by_lp",
+    nativeToScVal(lp, { type: "address" }),
+    nativeToScVal(page, { type: "u32" }),
+    nativeToScVal(pageSize, { type: "u32" })
+  );
+ 
+  const tx = new TransactionBuilder(sourceAccount, {
+    fee: BASE_FEE,
+    networkPassphrase,
+  })
+    .addOperation(op)
+    .setTimeout(30)
+    .build();
+ 
+  const sim = await server.simulateTransaction(tx);
+ 
+  Iif (SorobanRpc.Api.isSimulationError(sim)) {
+    throw ILNError.fromError(sim.error);
+  }
+  Iif (!sim.result?.retval) {
+    return [];
+  }
+ 
+  const rawArr = scValToNative(sim.result.retval) as Record<string, unknown>[];
+  return rawArr.map(raw => {
+    const dueDate = Number(raw["due_date"]);
+    const discountRate = Number(raw["discount_rate"]);
+    return {
+      id: BigInt(String(raw["id"])),
+      freelancer: String(raw["freelancer"]),
+      payer: String(raw["payer"]),
+      token: String(raw["token"]),
+      amount: BigInt(String(raw["amount"])),
+      dueDate,
+      discountRate,
+      status: (raw["status"] as any)?.tag || String(raw["status"]) as any,
+      funder: raw["funder"] ? String(raw["funder"]) : undefined,
+      fundedAt: raw["funded_at"] ? Number(raw["funded_at"]) : undefined,
+      amountFunded: BigInt(String(raw["amount_funded"])),
+      amountPaid: BigInt(String(raw["amount_paid"])),
+      referralCode: raw["referral_code"] ? Buffer.from(raw["referral_code"] as any).toString('hex') : undefined,
+      submitterReputation: Number(raw["submitter_reputation"]),
+      effectiveYieldBps: computeEffectiveYieldBps(discountRate, dueDate),
+    };
+  });
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/reputation.d.ts.html b/sdk/coverage/lcov-report/src/methods/reputation.d.ts.html new file mode 100644 index 00000000..045f4468 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/reputation.d.ts.html @@ -0,0 +1,229 @@ + + + + + + Code coverage report for src/methods/reputation.d.ts + + + + + + + + + +
+
+

All files / src/methods reputation.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * getReputation — read an address's detailed reputation profile from
+ * the on-chain invoice-liquidity contract.
+ *
+ * Wraps the `get_reputation(address)` view function. Unknown addresses
+ * return a zeroed profile (matching the contract's lazy-init behaviour).
+ */
+import { SorobanRpc } from "@stellar/stellar-sdk";
+/**
+ * An address's on-chain reputation profile.
+ *
+ * Mirrors `ReputationProfile` in the Rust contract (`invoice.rs`).
+ * Unknown addresses return every field as zero.
+ */
+export interface ReputationProfile {
+    /** Stellar G… address that was queried. */
+    address: string;
+    /** Current reputation score (0–100). */
+    score: number;
+    /** Total invoices submitted by this address. */
+    invoicesSubmitted: number;
+    /** Total invoices paid by this address (as payer). */
+    invoicesPaid: number;
+    /** Total invoices defaulted by this address. */
+    invoicesDefaulted: number;
+}
+/**
+ * Query the reputation profile for a Stellar address.
+ *
+ * Performs a read-only Soroban simulation — no on-chain mutation, no
+ * transaction fees, and no signer required.
+ *
+ * @param server              - Soroban RPC server for the target network
+ * @param contractId          - Deployed invoice-liquidity contract address
+ * @param address             - Stellar G… address to look up
+ * @param networkPassphrase   - Stellar network passphrase (default: TESTNET)
+ * @returns ReputationProfile (zeroed for unknown / never-active addresses)
+ *
+ * @throws When `address` is not a valid Stellar G-address
+ * @throws When the Soroban simulation fails (RPC unreachable, contract not found)
+ *
+ * @example
+ * ```ts
+ * const rep = await getReputation(server, CONTRACT_ID, "GAA...");
+ * console.log(`Score: ${rep.score}, Submitted: ${rep.invoicesSubmitted}`);
+ * ```
+ */
+export declare function getReputation(server: SorobanRpc.Server, contractId: string, address: string, networkPassphrase?: string): Promise<ReputationProfile>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/reputation.ts.html b/sdk/coverage/lcov-report/src/methods/reputation.ts.html new file mode 100644 index 00000000..cb257362 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/reputation.ts.html @@ -0,0 +1,490 @@ + + + + + + Code coverage report for src/methods/reputation.ts + + + + + + + + + +
+
+

All files / src/methods reputation.ts

+
+ +
+ 0% + Statements + 0/15 +
+ + +
+ 0% + Branches + 0/14 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/15 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * getReputation — read an address's detailed reputation profile from
+ * the on-chain invoice-liquidity contract.
+ *
+ * Wraps the `get_reputation(address)` view function. Unknown addresses
+ * return a zeroed profile (matching the contract's lazy-init behaviour).
+ */
+ 
+import {
+  Contract,
+  SorobanRpc,
+  TransactionBuilder,
+  Account,
+  BASE_FEE,
+  scValToNative,
+  Address,
+  Networks,
+} from "@stellar/stellar-sdk";
+ 
+// ---------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------
+ 
+/**
+ * An address's on-chain reputation profile.
+ *
+ * Mirrors `ReputationProfile` in the Rust contract (`invoice.rs`).
+ * Unknown addresses return every field as zero.
+ */
+export interface ReputationProfile {
+  /** Stellar G… address that was queried. */
+  address: string;
+  /** Current reputation score (0–100). */
+  score: number;
+  /** Total invoices submitted by this address. */
+  invoicesSubmitted: number;
+  /** Total invoices paid by this address (as payer). */
+  invoicesPaid: number;
+  /** Total invoices defaulted by this address. */
+  invoicesDefaulted: number;
+}
+ 
+// ---------------------------------------------------------------------------
+// G-address validation
+// ---------------------------------------------------------------------------
+ 
+const G_ADDRESS_RE = /^G[A-Z2-7]{55}$/;
+ 
+function isValidGAddress(address: string): boolean {
+  return G_ADDRESS_RE.test(address);
+}
+ 
+// ---------------------------------------------------------------------------
+// getReputation
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Query the reputation profile for a Stellar address.
+ *
+ * Performs a read-only Soroban simulation — no on-chain mutation, no
+ * transaction fees, and no signer required.
+ *
+ * @param server              - Soroban RPC server for the target network
+ * @param contractId          - Deployed invoice-liquidity contract address
+ * @param address             - Stellar G… address to look up
+ * @param networkPassphrase   - Stellar network passphrase (default: TESTNET)
+ * @returns ReputationProfile (zeroed for unknown / never-active addresses)
+ *
+ * @throws When `address` is not a valid Stellar G-address
+ * @throws When the Soroban simulation fails (RPC unreachable, contract not found)
+ *
+ * @example
+ * ```ts
+ * const rep = await getReputation(server, CONTRACT_ID, "GAA...");
+ * console.log(`Score: ${rep.score}, Submitted: ${rep.invoicesSubmitted}`);
+ * ```
+ */
+export async function getReputation(
+  server: SorobanRpc.Server,
+  contractId: string,
+  address: string,
+  networkPassphrase: string = Networks.TESTNET
+): Promise<ReputationProfile> {
+  Iif (!isValidGAddress(address)) {
+    throw new Error(
+      `Invalid Stellar address: "${address}". Must be a G… public key.`
+    );
+  }
+ 
+  const contract = new Contract(contractId);
+  const op = contract.call(
+    "get_reputation",
+    new Address(address).toScVal()
+  );
+ 
+  const sourceAccount = new Account(
+    "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF",
+    "0"
+  );
+ 
+  const simTx = new TransactionBuilder(sourceAccount, {
+    fee: BASE_FEE,
+    networkPassphrase,
+  })
+    .addOperation(op)
+    .setTimeout(30)
+    .build();
+ 
+  const sim = await server.simulateTransaction(simTx);
+ 
+  Iif (SorobanRpc.Api.isSimulationError(sim)) {
+    throw new Error(`get_reputation simulation failed: ${sim.error}`);
+  }
+ 
+  // The contract returns a zeroed ReputationProfile for unknown addresses
+  Iif (!sim.result?.retval) {
+    return {
+      address,
+      score: 0,
+      invoicesSubmitted: 0,
+      invoicesPaid: 0,
+      invoicesDefaulted: 0,
+    };
+  }
+ 
+  const raw = scValToNative(sim.result.retval) as Record<string, unknown>;
+ 
+  return {
+    address: String(raw["address"] ?? address),
+    score: Number(raw["score"] ?? 0),
+    invoicesSubmitted: Number(raw["invoices_submitted"] ?? 0),
+    invoicesPaid: Number(raw["invoices_paid"] ?? 0),
+    invoicesDefaulted: Number(raw["invoices_defaulted"] ?? 0),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/stats.d.ts.html b/sdk/coverage/lcov-report/src/methods/stats.d.ts.html new file mode 100644 index 00000000..a0299345 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/stats.d.ts.html @@ -0,0 +1,235 @@ + + + + + + Code coverage report for src/methods/stats.d.ts + + + + + + + + + +
+
+

All files / src/methods stats.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * getContractStats — fetch protocol-wide statistics from the contract.
+ *
+ * Reads the single `get_contract_stats()` view call. No signer or
+ * transaction fees required (read-only simulation).
+ */
+import { SorobanRpc } from "@stellar/stellar-sdk";
+/**
+ * Protocol-wide statistics returned by `get_contract_stats()`.
+ *
+ * Mirrors `ContractStats` in the Rust contract.
+ */
+export interface ContractStats {
+    /** Total number of invoices ever created. */
+    totalInvoices: bigint;
+    /** Cumulative number of fully-funded invoices. */
+    totalFunded: bigint;
+    /** Cumulative number of paid invoices. */
+    totalPaid: bigint;
+    /** Total USDC volume (in stroops, 6 decimals). */
+    totalVolumeUsdc: bigint;
+    /** Total EURC volume (in stroops, 6 decimals). */
+    totalVolumeEurc: bigint;
+    /** Total XLM volume (in stroops, 7 decimals). */
+    totalVolumeXlm: bigint;
+    /** Per-token volume map: token address → volume. */
+    volumeByToken: Record<string, bigint>;
+    /** Total volume normalized to USD (depends on oracle price feed). */
+    totalVolumeUsdNormalized: bigint;
+}
+/**
+ * Query protocol-wide statistics from the contract.
+ *
+ * Read-only — no signer, no fees, no on-chain mutation.
+ *
+ * @param server              - Soroban RPC server for the target network
+ * @param contractId          - Deployed invoice-liquidity contract address
+ * @param networkPassphrase   - Stellar network passphrase (default: TESTNET)
+ * @returns ContractStats
+ *
+ * @throws When the Soroban simulation fails (RPC unreachable, contract not found)
+ *
+ * @example
+ * ```ts
+ * const stats = await getContractStats(server, CONTRACT_ID);
+ * console.log(`Total invoices: ${stats.totalInvoices}`);
+ * console.log(`USDC volume:    ${stats.totalVolumeUsdc}`);
+ * ```
+ */
+export declare function getContractStats(server: SorobanRpc.Server, contractId: string, networkPassphrase?: string): Promise<ContractStats>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/stats.ts.html b/sdk/coverage/lcov-report/src/methods/stats.ts.html new file mode 100644 index 00000000..079b0090 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/stats.ts.html @@ -0,0 +1,481 @@ + + + + + + Code coverage report for src/methods/stats.ts + + + + + + + + + +
+
+

All files / src/methods stats.ts

+
+ +
+ 0% + Statements + 0/16 +
+ + +
+ 0% + Branches + 0/18 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/16 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * getContractStats — fetch protocol-wide statistics from the contract.
+ *
+ * Reads the single `get_contract_stats()` view call. No signer or
+ * transaction fees required (read-only simulation).
+ */
+ 
+import {
+  Contract,
+  SorobanRpc,
+  TransactionBuilder,
+  Account,
+  BASE_FEE,
+  scValToNative,
+  Networks,
+} from "@stellar/stellar-sdk";
+ 
+// ---------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Protocol-wide statistics returned by `get_contract_stats()`.
+ *
+ * Mirrors `ContractStats` in the Rust contract.
+ */
+export interface ContractStats {
+  /** Total number of invoices ever created. */
+  totalInvoices: bigint;
+  /** Cumulative number of fully-funded invoices. */
+  totalFunded: bigint;
+  /** Cumulative number of paid invoices. */
+  totalPaid: bigint;
+  /** Total USDC volume (in stroops, 6 decimals). */
+  totalVolumeUsdc: bigint;
+  /** Total EURC volume (in stroops, 6 decimals). */
+  totalVolumeEurc: bigint;
+  /** Total XLM volume (in stroops, 7 decimals). */
+  totalVolumeXlm: bigint;
+  /** Per-token volume map: token address → volume. */
+  volumeByToken: Record<string, bigint>;
+  /** Total volume normalized to USD (depends on oracle price feed). */
+  totalVolumeUsdNormalized: bigint;
+}
+ 
+// ---------------------------------------------------------------------------
+// getContractStats
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Query protocol-wide statistics from the contract.
+ *
+ * Read-only — no signer, no fees, no on-chain mutation.
+ *
+ * @param server              - Soroban RPC server for the target network
+ * @param contractId          - Deployed invoice-liquidity contract address
+ * @param networkPassphrase   - Stellar network passphrase (default: TESTNET)
+ * @returns ContractStats
+ *
+ * @throws When the Soroban simulation fails (RPC unreachable, contract not found)
+ *
+ * @example
+ * ```ts
+ * const stats = await getContractStats(server, CONTRACT_ID);
+ * console.log(`Total invoices: ${stats.totalInvoices}`);
+ * console.log(`USDC volume:    ${stats.totalVolumeUsdc}`);
+ * ```
+ */
+export async function getContractStats(
+  server: SorobanRpc.Server,
+  contractId: string,
+  networkPassphrase: string = Networks.TESTNET
+): Promise<ContractStats> {
+  const contract = new Contract(contractId);
+  const op = contract.call("get_contract_stats");
+ 
+  const sourceAccount = new Account(
+    "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF",
+    "0"
+  );
+ 
+  const simTx = new TransactionBuilder(sourceAccount, {
+    fee: BASE_FEE,
+    networkPassphrase,
+  })
+    .addOperation(op)
+    .setTimeout(30)
+    .build();
+ 
+  const sim = await server.simulateTransaction(simTx);
+ 
+  Iif (SorobanRpc.Api.isSimulationError(sim)) {
+    throw new Error(`get_contract_stats simulation failed: ${sim.error}`);
+  }
+ 
+  Iif (!sim.result?.retval) {
+    return {
+      totalInvoices: 0n,
+      totalFunded: 0n,
+      totalPaid: 0n,
+      totalVolumeUsdc: 0n,
+      totalVolumeEurc: 0n,
+      totalVolumeXlm: 0n,
+      volumeByToken: {},
+      totalVolumeUsdNormalized: 0n,
+    };
+  }
+ 
+  const raw = scValToNative(sim.result.retval) as Record<string, unknown>;
+ 
+  // Parse per-token volumes: the contract returns a Vec<(Address, i128)>
+  const volumeByToken: Record<string, bigint> = {};
+  const rawTokenVolumes = raw["token_volumes"] as Array<[string, string]> | undefined;
+  Iif (Array.isArray(rawTokenVolumes)) {
+    for (const [token, volume] of rawTokenVolumes) {
+      volumeByToken[token] = BigInt(volume);
+    }
+  }
+ 
+  return {
+    totalInvoices: BigInt(String(raw["total_invoices"] ?? "0")),
+    totalFunded: BigInt(String(raw["total_funded"] ?? "0")),
+    totalPaid: BigInt(String(raw["total_paid"] ?? "0")),
+    totalVolumeUsdc: BigInt(String(raw["total_volume_usdc"] ?? "0")),
+    totalVolumeEurc: BigInt(String(raw["total_volume_eurc"] ?? "0")),
+    totalVolumeXlm: BigInt(String(raw["total_volume_xlm"] ?? "0")),
+    volumeByToken,
+    totalVolumeUsdNormalized: BigInt(
+      String(raw["total_volume_usd_normalized"] ?? "0")
+    ),
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/submitInvoice.d.ts.html b/sdk/coverage/lcov-report/src/methods/submitInvoice.d.ts.html new file mode 100644 index 00000000..af1bfe10 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/submitInvoice.d.ts.html @@ -0,0 +1,157 @@ + + + + + + Code coverage report for src/methods/submitInvoice.d.ts + + + + + + + + + +
+
+

All files / src/methods submitInvoice.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { SorobanRpc, Account, Transaction } from "@stellar/stellar-sdk";
+import type { SubmitInvoiceParams, SubmitInvoiceResult } from "../types/params.js";
+/**
+ * Submit a new invoice to the contract.
+ * @param server Soroban RPC server
+ * @param contractAddress Contract address
+ * @param params Invoice parameters
+ * @param sourceAccount The account of the freelancer/submitter
+ * @param signTransaction A function to sign the transaction (e.g. Freighter or Keypair)
+ * @param networkPassphrase The network passphrase
+ * @returns Object containing invoiceId and txHash
+ * @throws {ILNError.InvalidAmount} If amount is <= 0
+ * @throws {ILNError.InvalidDiscountRate} If discount rate is not between 1 and 5000 bps
+ * @throws {ILNError.DueDateTooSoon} If due date is < 24h
+ * @throws {ILNError.DueDateTooFar} If due date is > 365 days
+ * @throws {ILNError} If payer address is invalid or transaction fails
+ * @example
+ * ```ts
+ * const { invoiceId, txHash } = await submitInvoice(server, contractAddress, {
+ *   payer: "G...", amount: 1000n, dueDate: Date.now() / 1000 + 86400 * 30, discountRate: 300, token: "C..."
+ * }, sourceAccount, signTx, Networks.TESTNET);
+ * ```
+ */
+export declare function submitInvoice(server: SorobanRpc.Server, contractAddress: string, params: SubmitInvoiceParams, sourceAccount: Account, signTransaction: (tx: Transaction) => Promise<Transaction> | Transaction, networkPassphrase: string): Promise<SubmitInvoiceResult>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/methods/transferLPPosition.d.ts.html b/sdk/coverage/lcov-report/src/methods/transferLPPosition.d.ts.html new file mode 100644 index 00000000..78813623 --- /dev/null +++ b/sdk/coverage/lcov-report/src/methods/transferLPPosition.d.ts.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/methods/transferLPPosition.d.ts + + + + + + + + + +
+
+

All files / src/methods transferLPPosition.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { SorobanRpc, Account, Transaction } from "@stellar/stellar-sdk";
+/**
+ * Transfer a funded LP position to another address.
+ *
+ * Allows a liquidity provider to exit a position they have funded by handing
+ * it to a new LP, without unwinding the underlying invoice. The caller
+ * (`sourceAccount`) must be the current LP of the position.
+ *
+ * @param server Soroban RPC server
+ * @param contractAddress Contract address
+ * @param invoiceId The ID of the funded invoice whose position is transferred
+ * @param newLP The G-address of the LP receiving the position
+ * @param sourceAccount The account of the current LP
+ * @param signTransaction A function to sign the transaction (e.g. Freighter or Keypair)
+ * @param networkPassphrase The network passphrase
+ * @returns Object containing txHash
+ * @throws {ILNError.InvalidAddress} If newLP is not a valid Stellar G-address
+ * @throws {ILNError.InvalidTransfer} If newLP is the same as the current LP
+ * @throws {ILNError} When simulation or execution fails
+ * @example
+ * ```ts
+ * const { txHash } = await transferLPPosition(server, contractAddress, 42n, "G...", sourceAccount, signTx, Networks.TESTNET);
+ * ```
+ */
+export declare function transferLPPosition(server: SorobanRpc.Server, contractAddress: string, invoiceId: bigint, newLP: string, sourceAccount: Account, signTransaction: (tx: Transaction) => Promise<Transaction> | Transaction, networkPassphrase: string): Promise<{
+    txHash: string;
+}>;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/signers/FreighterSigner.d.ts.html b/sdk/coverage/lcov-report/src/signers/FreighterSigner.d.ts.html new file mode 100644 index 00000000..bdcb16c4 --- /dev/null +++ b/sdk/coverage/lcov-report/src/signers/FreighterSigner.d.ts.html @@ -0,0 +1,514 @@ + + + + + + Code coverage report for src/signers/FreighterSigner.d.ts + + + + + + + + + +
+
+

All files / src/signers FreighterSigner.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * FreighterSigner — ISigner adapter for the Freighter browser extension.
+ *
+ * Intended for browser-based dApps where a Stellar wallet extension is
+ * available. Detects whether Freighter is installed, requests network
+ * access on first use, and delegates transaction signing to the wallet.
+ *
+ * ## Flow
+ *
+ *   1. `constructor` — stores configuration; does NOT touch the wallet.
+ *   2. `publicKey` getter — triggers detection + access request, then caches
+ *      the public key for the session.
+ *   3. `signTransaction()` — hands the prepared XDR envelope to Freighter
+ *      and returns the signed envelope as a base-64 string.
+ *
+ * ## Error handling
+ *
+ *   - `ILNError.WalletNotInstalled` — `window.freighterApi` is undefined
+ *   - `ILNError.UserRejected`        — the user dismissed the Freighter prompt
+ *   - `ILNError.NetworkMismatch`     — the wallet network differs from the
+ *       configured network (e.g. wallet on mainnet but SDK on testnet)
+ *
+ * ## Network-mismatch detection
+ *
+ * Freighter returns the active network via `getNetwork()` (or
+ * `getNetworkDetails()`). Before signing we compare it against the
+ * configured `networkPassphrase` and throw `NetworkMismatch` when they
+ * differ, avoiding hard-to-debug simulation failures downstream.
+ */
+import { SorobanRpc } from "@stellar/stellar-sdk";
+import type { ISigner } from "./ISigner.js";
+import type { Transaction } from "@stellar/stellar-sdk";
+interface FreighterApi {
+    isConnected(): Promise<boolean>;
+    getPublicKey(): Promise<string>;
+    getNetwork(): Promise<string>;
+    signTransaction(xdr: string, opts?: {
+        network?: string;
+        networkPassphrase?: string;
+    }): Promise<string>;
+}
+declare global {
+    interface Window {
+        freighterApi?: FreighterApi;
+    }
+}
+/** SDK-level error with a machine-readable code. */
+export declare class ILNError extends Error {
+    readonly code: ILNErrorCode;
+    constructor(code: ILNErrorCode, message: string);
+    static WalletNotInstalled(): ILNError;
+    static UserRejected(): ILNError;
+    static NetworkMismatch(expected: string, actual: string): ILNError;
+    static NotConnected(): ILNError;
+}
+/** Error codes for programmatic handling. */
+export declare enum ILNErrorCode {
+    WalletNotInstalled = "WALLET_NOT_INSTALLED",
+    UserRejected = "USER_REJECTED",
+    NetworkMismatch = "NETWORK_MISMATCH",
+    NotConnected = "NOT_CONNECTED",
+    SigningFailed = "SIGNING_FAILED"
+}
+/**
+ * Browser wallet signer backed by the Freighter extension.
+ *
+ * @example
+ * ```ts
+ * // Testnet
+ * const signer = new FreighterSigner({ networkPassphrase: Networks.TESTNET });
+ * console.log(signer.publicKey); // triggers Freighter access prompt
+ *
+ * // Mainnet
+ * const signer = new FreighterSigner({ networkPassphrase: Networks.PUBLIC });
+ *
+ * // Sign a transaction
+ * const signedXdr = await signer.signTransaction(tx, rpcServer);
+ * ```
+ */
+export declare class FreighterSigner implements ISigner {
+    private readonly _networkPassphrase;
+    private _publicKey;
+    private _accessRequested;
+    /**
+     * @param opts.networkPassphrase - Stellar network passphrase the SDK is
+     *   targeting (e.g. `Networks.TESTNET`). Used to verify Freighter's active
+     *   network before signing.
+     */
+    constructor(opts: {
+        networkPassphrase: string;
+    });
+    /**
+     * The Freighter account's G… public key.
+     *
+     * Returns an empty string `""` until `connect()` has been called
+     * successfully. Use `isConnected` to check whether the public key is
+     * available, or call `connect()` early (e.g. on page load) so the
+     * key is populated before it's needed.
+     */
+    get publicKey(): string;
+    /**
+     * Explicitly connect to Freighter, request access, and cache the public key.
+     *
+     * Call this early (e.g. on page load) so `publicKey` is available
+     * synchronously afterwards.
+     *
+     * @returns The public key (G…)
+     * @throws {ILNError} WalletNotInstalled | NotConnected | UserRejected | NetworkMismatch
+     */
+    connect(): Promise<string>;
+    /**
+     * Simulate the transaction, then sign with Freighter and return the
+     * signed XDR envelope.
+     *
+     * Steps:
+     *  1. `server.prepareTransaction(tx)` — attaches Soroban footprint
+     *  2. Serialize to base-64 XDR
+     *  3. Pass to Freighter's `signTransaction`
+     *  4. Return the signed XDR
+     *
+     * @param tx     - Unsigned transaction with Soroban operations
+     * @param server - Soroban RPC server for simulation
+     * @returns Signed base-64 XDR envelope
+     * @throws {ILNError} WalletNotInstalled | NotConnected | UserRejected | NetworkMismatch
+     */
+    signTransaction(tx: Transaction, server: SorobanRpc.Server): Promise<string>;
+    /** The configured network passphrase. */
+    get networkPassphrase(): string;
+    /** True once `connect()` has succeeded. */
+    get isConnected(): boolean;
+    /** Throw if the Freighter extension isn't installed. */
+    private _ensureInstalled;
+    /** Return the Freighter API object (asserts it's installed). */
+    private _api;
+    /**
+     * Compare the wallet's active network against the configured passphrase.
+     * Throws `NetworkMismatch` when they diverge.
+     */
+    private _verifyNetwork;
+    /** Classify a raw error from Freighter into a typed ILNError. */
+    private _classifySignError;
+}
+export {};
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/signers/FreighterSigner.ts.html b/sdk/coverage/lcov-report/src/signers/FreighterSigner.ts.html new file mode 100644 index 00000000..e4d8a1d5 --- /dev/null +++ b/sdk/coverage/lcov-report/src/signers/FreighterSigner.ts.html @@ -0,0 +1,1135 @@ + + + + + + Code coverage report for src/signers/FreighterSigner.ts + + + + + + + + + +
+
+

All files / src/signers FreighterSigner.ts

+
+ +
+ 0% + Statements + 0/66 +
+ + +
+ 0% + Branches + 0/36 +
+ + +
+ 0% + Functions + 0/16 +
+ + +
+ 0% + Lines + 0/65 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * FreighterSigner — ISigner adapter for the Freighter browser extension.
+ *
+ * Intended for browser-based dApps where a Stellar wallet extension is
+ * available. Detects whether Freighter is installed, requests network
+ * access on first use, and delegates transaction signing to the wallet.
+ *
+ * ## Flow
+ *
+ *   1. `constructor` — stores configuration; does NOT touch the wallet.
+ *   2. `publicKey` getter — triggers detection + access request, then caches
+ *      the public key for the session.
+ *   3. `signTransaction()` — hands the prepared XDR envelope to Freighter
+ *      and returns the signed envelope as a base-64 string.
+ *
+ * ## Error handling
+ *
+ *   - `ILNError.WalletNotInstalled` — `window.freighterApi` is undefined
+ *   - `ILNError.UserRejected`        — the user dismissed the Freighter prompt
+ *   - `ILNError.NetworkMismatch`     — the wallet network differs from the
+ *       configured network (e.g. wallet on mainnet but SDK on testnet)
+ *
+ * ## Network-mismatch detection
+ *
+ * Freighter returns the active network via `getNetwork()` (or
+ * `getNetworkDetails()`). Before signing we compare it against the
+ * configured `networkPassphrase` and throw `NetworkMismatch` when they
+ * differ, avoiding hard-to-debug simulation failures downstream.
+ */
+ 
+import { Networks, SorobanRpc } from "@stellar/stellar-sdk";
+import type { ISigner } from "./ISigner.js";
+import type { Transaction } from "@stellar/stellar-sdk";
+ 
+// ---------------------------------------------------------------------------
+// Freighter browser API (subset of @stellar/freighter-api)
+// ---------------------------------------------------------------------------
+ 
+interface FreighterApi {
+  isConnected(): Promise<boolean>;
+  getPublicKey(): Promise<string>;
+  getNetwork(): Promise<string>;
+  signTransaction(
+    xdr: string,
+    opts?: { network?: string; networkPassphrase?: string }
+  ): Promise<string>;
+}
+ 
+declare global {
+  interface Window {
+    freighterApi?: FreighterApi;
+  }
+}
+ 
+// ---------------------------------------------------------------------------
+// ILNError
+// ---------------------------------------------------------------------------
+ 
+/** SDK-level error with a machine-readable code. */
+export class ILNError extends Error {
+  public readonly code: ILNErrorCode;
+ 
+  constructor(code: ILNErrorCode, message: string) {
+    super(message);
+    this.name = "ILNError";
+    this.code = code;
+  }
+ 
+  static WalletNotInstalled(): ILNError {
+    return new ILNError(
+      ILNErrorCode.WalletNotInstalled,
+      "Freighter is not installed. Please install the Freighter browser extension."
+    );
+  }
+ 
+  static UserRejected(): ILNError {
+    return new ILNError(
+      ILNErrorCode.UserRejected,
+      "The user rejected the Freighter request."
+    );
+  }
+ 
+  static NetworkMismatch(expected: string, actual: string): ILNError {
+    return new ILNError(
+      ILNErrorCode.NetworkMismatch,
+      `Network mismatch: SDK expects "${expected}" but Freighter is on "${actual}". Please switch your wallet network.`
+    );
+  }
+ 
+  static NotConnected(): ILNError {
+    return new ILNError(
+      ILNErrorCode.NotConnected,
+      "Freighter is locked or not connected. Please unlock the extension."
+    );
+  }
+}
+ 
+/** Error codes for programmatic handling. */
+export enum ILNErrorCode {
+  WalletNotInstalled = "WALLET_NOT_INSTALLED",
+  UserRejected = "USER_REJECTED",
+  NetworkMismatch = "NETWORK_MISMATCH",
+  NotConnected = "NOT_CONNECTED",
+  SigningFailed = "SIGNING_FAILED",
+}
+ 
+// ---------------------------------------------------------------------------
+// Network passphrase ↔ Freighter network name mapping
+// ---------------------------------------------------------------------------
+ 
+const PASSPHRASE_TO_FREIGHTER: Record<string, string> = {
+  [Networks.PUBLIC]: "PUBLIC",
+  [Networks.TESTNET]: "TESTNET",
+};
+ 
+const FREIGHTER_TO_PASSPHRASE: Record<string, string> = {
+  PUBLIC: Networks.PUBLIC,
+  TESTNET: Networks.TESTNET,
+  FUTURENET: "Test SDF Future Network ; October 2022",
+};
+ 
+// ---------------------------------------------------------------------------
+// FreighterSigner
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Browser wallet signer backed by the Freighter extension.
+ *
+ * @example
+ * ```ts
+ * // Testnet
+ * const signer = new FreighterSigner({ networkPassphrase: Networks.TESTNET });
+ * console.log(signer.publicKey); // triggers Freighter access prompt
+ *
+ * // Mainnet
+ * const signer = new FreighterSigner({ networkPassphrase: Networks.PUBLIC });
+ *
+ * // Sign a transaction
+ * const signedXdr = await signer.signTransaction(tx, rpcServer);
+ * ```
+ */
+export class FreighterSigner implements ISigner {
+  private readonly _networkPassphrase: string;
+  private _publicKey: string | null = null;
+  private _accessRequested = false;
+ 
+  /**
+   * @param opts.networkPassphrase - Stellar network passphrase the SDK is
+   *   targeting (e.g. `Networks.TESTNET`). Used to verify Freighter's active
+   *   network before signing.
+   */
+  constructor(opts: { networkPassphrase: string }) {
+    this._networkPassphrase = opts.networkPassphrase;
+  }
+ 
+  // --------------------------------------------------------------------------
+  // ISigner
+  // --------------------------------------------------------------------------
+ 
+  /**
+   * The Freighter account's G… public key.
+   *
+   * Returns an empty string `""` until `connect()` has been called
+   * successfully. Use `isConnected` to check whether the public key is
+   * available, or call `connect()` early (e.g. on page load) so the
+   * key is populated before it's needed.
+   */
+  get publicKey(): string {
+    return this._publicKey ?? "";
+  }
+ 
+  /**
+   * Explicitly connect to Freighter, request access, and cache the public key.
+   *
+   * Call this early (e.g. on page load) so `publicKey` is available
+   * synchronously afterwards.
+   *
+   * @returns The public key (G…)
+   * @throws {ILNError} WalletNotInstalled | NotConnected | UserRejected | NetworkMismatch
+   */
+  async connect(): Promise<string> {
+    this._ensureInstalled();
+ 
+    Iif (!(await this._api().isConnected())) {
+      // Freighter is installed but locked / not connected
+      throw ILNError.NotConnected();
+    }
+ 
+    // Request access (shows Freighter prompt). Freighter's getPublicKey also
+    // triggers the access prompt if not yet granted.
+    const pk = await this._api().getPublicKey();
+ 
+    Iif (!pk || pk.length === 0) {
+      throw ILNError.UserRejected();
+    }
+ 
+    // Verify network
+    await this._verifyNetwork();
+ 
+    this._publicKey = pk;
+    this._accessRequested = true;
+    return pk;
+  }
+ 
+  /**
+   * Simulate the transaction, then sign with Freighter and return the
+   * signed XDR envelope.
+   *
+   * Steps:
+   *  1. `server.prepareTransaction(tx)` — attaches Soroban footprint
+   *  2. Serialize to base-64 XDR
+   *  3. Pass to Freighter's `signTransaction`
+   *  4. Return the signed XDR
+   *
+   * @param tx     - Unsigned transaction with Soroban operations
+   * @param server - Soroban RPC server for simulation
+   * @returns Signed base-64 XDR envelope
+   * @throws {ILNError} WalletNotInstalled | NotConnected | UserRejected | NetworkMismatch
+   */
+  async signTransaction(
+    tx: Transaction,
+    server: SorobanRpc.Server
+  ): Promise<string> {
+    // Ensure we are connected
+    Iif (!this._publicKey) {
+      await this.connect();
+    }
+ 
+    // Step 1: simulate to get the footprint
+    const preparedTx = await server.prepareTransaction(tx);
+ 
+    Iif (SorobanRpc.Api.isSimulationError(preparedTx as any)) {
+      throw new Error(
+        `Soroban simulation failed: ${(preparedTx as any).error}`
+      );
+    }
+ 
+    // Step 2: serialise to base-64 XDR
+    const envelopeXdr = (preparedTx as any)
+      .toEnvelope()
+      .toXDR("base64") as string;
+ 
+    // Step 3: ask Freighter to sign
+    const freighterNetwork = PASSPHRASE_TO_FREIGHTER[this._networkPassphrase];
+    Iif (!freighterNetwork) {
+      throw new Error(
+        `Unknown network passphrase: ${this._networkPassphrase}`
+      );
+    }
+ 
+    let signedXdr: string;
+    try {
+      signedXdr = await this._api().signTransaction(envelopeXdr, {
+        network: freighterNetwork,
+      });
+    } catch (err: unknown) {
+      throw this._classifySignError(err);
+    }
+ 
+    Iif (!signedXdr || signedXdr.length === 0) {
+      throw ILNError.UserRejected();
+    }
+ 
+    return signedXdr;
+  }
+ 
+  // --------------------------------------------------------------------------
+  // Accessors
+  // --------------------------------------------------------------------------
+ 
+  /** The configured network passphrase. */
+  get networkPassphrase(): string {
+    return this._networkPassphrase;
+  }
+ 
+  /** True once `connect()` has succeeded. */
+  get isConnected(): boolean {
+    return this._accessRequested && this._publicKey !== null;
+  }
+ 
+  // --------------------------------------------------------------------------
+  // Internals
+  // --------------------------------------------------------------------------
+ 
+  /** Throw if the Freighter extension isn't installed. */
+  private _ensureInstalled(): void {
+    // Use a two-step type assertion to safely access the browser global.
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    const g = globalThis as any;
+    Iif (typeof g.window === "undefined" || !g.window.freighterApi) {
+      throw ILNError.WalletNotInstalled();
+    }
+  }
+ 
+  /** Return the Freighter API object (asserts it's installed). */
+  private _api(): FreighterApi {
+    this._ensureInstalled();
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion
+    return (globalThis as any).window.freighterApi!;
+  }
+ 
+  /**
+   * Compare the wallet's active network against the configured passphrase.
+   * Throws `NetworkMismatch` when they diverge.
+   */
+  private async _verifyNetwork(): Promise<void> {
+    let walletNetwork: string;
+    try {
+      walletNetwork = await this._api().getNetwork();
+    } catch {
+      // Some older Freighter versions don't support getNetwork; skip check
+      return;
+    }
+ 
+    const expectedPassphrase = FREIGHTER_TO_PASSPHRASE[walletNetwork];
+    Iif (!expectedPassphrase) return; // unknown network; skip
+ 
+    Iif (expectedPassphrase !== this._networkPassphrase) {
+      throw ILNError.NetworkMismatch(
+        this._networkPassphrase,
+        expectedPassphrase
+      );
+    }
+  }
+ 
+  /** Classify a raw error from Freighter into a typed ILNError. */
+  private _classifySignError(err: unknown): ILNError {
+    const msg = typeof err === "string" ? err : (err as Error)?.message ?? "";
+ 
+    const lowered = msg.toLowerCase();
+ 
+    Iif (
+      lowered.includes("rejected") ||
+      lowered.includes("denied") ||
+      lowered.includes("cancelled") ||
+      lowered.includes("canceled")
+    ) {
+      return ILNError.UserRejected();
+    }
+ 
+    Iif (
+      lowered.includes("network mismatch") ||
+      (lowered.includes("network") && lowered.includes("switch"))
+    ) {
+      return ILNError.NetworkMismatch(this._networkPassphrase, "unknown");
+    }
+ 
+    return new ILNError(ILNErrorCode.SigningFailed, msg || "Freighter signing failed");
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/signers/ISigner.d.ts.html b/sdk/coverage/lcov-report/src/signers/ISigner.d.ts.html new file mode 100644 index 00000000..05bc1e0a --- /dev/null +++ b/sdk/coverage/lcov-report/src/signers/ISigner.d.ts.html @@ -0,0 +1,163 @@ + + + + + + Code coverage report for src/signers/ISigner.d.ts + + + + + + + + + +
+
+

All files / src/signers ISigner.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type { Transaction, SorobanRpc } from "@stellar/stellar-sdk";
+/**
+ * Common signer interface for all SDK signing adapters.
+ *
+ * Implement this interface to plug in browser wallets (Freighter, Albedo)
+ * or server-side signers (KeypairSigner) without changing call-site code.
+ */
+export interface ISigner {
+    /** Stellar public key (G…) of the signing account. */
+    readonly publicKey: string;
+    /**
+     * Simulate the transaction against a Soroban RPC node to obtain the
+     * Soroban footprint, then sign the prepared transaction and return the
+     * signed XDR envelope as a base-64 string.
+     *
+     * Implementations must:
+     *   1. Call `server.prepareTransaction(tx)` to attach the footprint.
+     *   2. Sign the prepared transaction with the underlying credentials.
+     *   3. Return `signedTx.toEnvelope().toXDR("base64")`.
+     *
+     * @param tx     - Unsigned Stellar transaction (already has operations)
+     * @param server - Soroban RPC server used for simulation
+     * @returns Base-64 XDR of the signed transaction envelope
+     */
+    signTransaction(tx: Transaction, server: SorobanRpc.Server): Promise<string>;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/signers/KeypairSigner.d.ts.html b/sdk/coverage/lcov-report/src/signers/KeypairSigner.d.ts.html new file mode 100644 index 00000000..5ef08c01 --- /dev/null +++ b/sdk/coverage/lcov-report/src/signers/KeypairSigner.d.ts.html @@ -0,0 +1,355 @@ + + + + + + Code coverage report for src/signers/KeypairSigner.d.ts + + + + + + + + + +
+
+

All files / src/signers KeypairSigner.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * KeypairSigner — ISigner adapter for raw Stellar keypairs.
+ *
+ * Intended for Node.js scripts, CLI tools, and bots where a browser wallet
+ * is not available. Accepts either a `Keypair` instance or a secret-key
+ * string (S…).
+ *
+ * Two-step flow on every `signTransaction()` call:
+ *   1. Simulate the transaction via `server.prepareTransaction()` to fetch
+ *      the Soroban footprint (ledger entries, auth entries, resource limits).
+ *   2. Sign the *prepared* transaction and return the signed XDR envelope.
+ *
+ * Security notice
+ * ---------------
+ * Hard-coding secret keys in source files is dangerous. KeypairSigner emits
+ * a `console.warn` when it detects that the process is not running inside a
+ * test environment (`NODE_ENV !== "test"`) **and** the secret was supplied as
+ * a plain string literal. Pass the secret via an environment variable instead:
+ *
+ * ```ts
+ * const signer = new KeypairSigner(process.env.LP_SECRET_KEY!);
+ * ```
+ */
+import { Keypair, SorobanRpc, Transaction } from "@stellar/stellar-sdk";
+import type { ISigner } from "./ISigner.js";
+/**
+ * Server-side ISigner backed by a Stellar keypair.
+ *
+ * @example
+ * ```ts
+ * // From environment variable (recommended)
+ * const signer = new KeypairSigner(process.env.LP_SECRET!);
+ *
+ * // From an existing Keypair instance
+ * const kp = Keypair.fromSecret(process.env.LP_SECRET!);
+ * const signer = new KeypairSigner(kp);
+ *
+ * // Sign a transaction
+ * const signedXdr = await signer.signTransaction(tx, rpcServer);
+ * ```
+ */
+export declare class KeypairSigner implements ISigner {
+    private readonly _keypair;
+    /**
+     * @param keypairOrSecret - A `Keypair` instance **or** a Stellar secret key
+     *   string starting with `S`. When a plain string is supplied outside of a
+     *   test environment a security warning is emitted.
+     */
+    constructor(keypairOrSecret: Keypair | string);
+    /** Stellar G… public key of this signer. */
+    get publicKey(): string;
+    /**
+     * Simulate the transaction to obtain the Soroban footprint, sign the
+     * prepared transaction, and return the signed XDR envelope as base-64.
+     *
+     * Steps:
+     *   1. `server.prepareTransaction(tx)` — attaches footprint + auth entries.
+     *   2. `preparedTx.sign(keypair)` — ECDSA/Ed25519 signature applied.
+     *   3. Returns `preparedTx.toEnvelope().toXDR("base64")`.
+     *
+     * @param tx     - Unsigned transaction with at least one Soroban operation
+     * @param server - Soroban RPC server used for simulation
+     * @returns Signed base-64 XDR envelope ready for `server.sendTransaction()`
+     *
+     * @throws {Error} When Soroban simulation fails (contract error, bad auth,
+     *   resource limit exceeded, etc.)
+     */
+    signTransaction(tx: Transaction, server: SorobanRpc.Server): Promise<string>;
+    /**
+     * Expose the underlying keypair for use-cases that need raw sign/verify
+     * access (e.g. building multi-sig transactions).
+     *
+     * Treat the returned keypair as read-only; do not call `keypair.sign()`
+     * directly on transaction envelopes — use `signTransaction()` so the
+     * simulation step is always executed.
+     */
+    get keypair(): Keypair;
+    /**
+     * Create a KeypairSigner from a secret key stored in an environment
+     * variable.
+     *
+     * ```ts
+     * const signer = KeypairSigner.fromEnv("LP_SECRET_KEY");
+     * ```
+     *
+     * @param envVar - Name of the environment variable holding the secret key
+     * @throws {Error} When the environment variable is not set
+     */
+    static fromEnv(envVar: string): KeypairSigner;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/signers/KeypairSigner.ts.html b/sdk/coverage/lcov-report/src/signers/KeypairSigner.ts.html new file mode 100644 index 00000000..5b27cf63 --- /dev/null +++ b/sdk/coverage/lcov-report/src/signers/KeypairSigner.ts.html @@ -0,0 +1,664 @@ + + + + + + Code coverage report for src/signers/KeypairSigner.ts + + + + + + + + + +
+
+

All files / src/signers KeypairSigner.ts

+
+ +
+ 0% + Statements + 0/24 +
+ + +
+ 0% + Branches + 0/9 +
+ + +
+ 0% + Functions + 0/7 +
+ + +
+ 0% + Lines + 0/23 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * KeypairSigner — ISigner adapter for raw Stellar keypairs.
+ *
+ * Intended for Node.js scripts, CLI tools, and bots where a browser wallet
+ * is not available. Accepts either a `Keypair` instance or a secret-key
+ * string (S…).
+ *
+ * Two-step flow on every `signTransaction()` call:
+ *   1. Simulate the transaction via `server.prepareTransaction()` to fetch
+ *      the Soroban footprint (ledger entries, auth entries, resource limits).
+ *   2. Sign the *prepared* transaction and return the signed XDR envelope.
+ *
+ * Security notice
+ * ---------------
+ * Hard-coding secret keys in source files is dangerous. KeypairSigner emits
+ * a `console.warn` when it detects that the process is not running inside a
+ * test environment (`NODE_ENV !== "test"`) **and** the secret was supplied as
+ * a plain string literal. Pass the secret via an environment variable instead:
+ *
+ * ```ts
+ * const signer = new KeypairSigner(process.env.LP_SECRET_KEY!);
+ * ```
+ */
+ 
+import { Keypair, SorobanRpc, Transaction } from "@stellar/stellar-sdk";
+import type { ISigner } from "./ISigner.js";
+ 
+// ---------------------------------------------------------------------------
+// Helpers
+// ---------------------------------------------------------------------------
+ 
+/** Detect a test environment heuristically. */
+function isTestEnvironment(): boolean {
+  return (
+    process.env["NODE_ENV"] === "test" ||
+    process.env["JEST_WORKER_ID"] !== undefined ||
+    process.env["VITEST"] !== undefined
+  );
+}
+ 
+/**
+ * Heuristic: a secret key that looks like it was pasted literally into source
+ * rather than read from the environment.  We flag when the value is a
+ * hardcoded default / example key or when it begins with `S` and
+ * `SECRET`/`PRIVATE` are not in the source call-stack (impossible to detect
+ * reliably, so we only warn, never block).
+ */
+function warnIfHardcodedSecret(secret: string): void {
+  Iif (isTestEnvironment()) return;
+ 
+  // Well-known example keys used in docs / tutorials
+  const knownExamples = new Set([
+    "SCZANGBA5RLAZ7IQVXSRQD5KXJLJPNWZPWHSB4TWJNSC2DL5CGFJ6Y2",
+    "SDASDASDASDASDASDASDASDASDASDASDASDASDASDASDASDASDA",
+  ]);
+ 
+  Iif (knownExamples.has(secret)) {
+    console.warn(
+      "[KeypairSigner] WARNING: You appear to be using a well-known example " +
+        "secret key. Never use example keys in production."
+    );
+    return;
+  }
+ 
+  // Generic warning: secret supplied as a string literal rather than via env
+  console.warn(
+    "[KeypairSigner] WARNING: Passing a secret key as a plain string is " +
+      "risky. Load it from an environment variable instead: " +
+      "new KeypairSigner(process.env.SECRET_KEY!)"
+  );
+}
+ 
+// ---------------------------------------------------------------------------
+// KeypairSigner
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Server-side ISigner backed by a Stellar keypair.
+ *
+ * @example
+ * ```ts
+ * // From environment variable (recommended)
+ * const signer = new KeypairSigner(process.env.LP_SECRET!);
+ *
+ * // From an existing Keypair instance
+ * const kp = Keypair.fromSecret(process.env.LP_SECRET!);
+ * const signer = new KeypairSigner(kp);
+ *
+ * // Sign a transaction
+ * const signedXdr = await signer.signTransaction(tx, rpcServer);
+ * ```
+ */
+export class KeypairSigner implements ISigner {
+  private readonly _keypair: Keypair;
+ 
+  /**
+   * @param keypairOrSecret - A `Keypair` instance **or** a Stellar secret key
+   *   string starting with `S`. When a plain string is supplied outside of a
+   *   test environment a security warning is emitted.
+   */
+  constructor(keypairOrSecret: Keypair | string) {
+    if (typeof keypairOrSecret === "string") {
+      warnIfHardcodedSecret(keypairOrSecret);
+      this._keypair = Keypair.fromSecret(keypairOrSecret);
+    } else {
+      this._keypair = keypairOrSecret;
+    }
+  }
+ 
+  // --------------------------------------------------------------------------
+  // ISigner
+  // --------------------------------------------------------------------------
+ 
+  /** Stellar G… public key of this signer. */
+  get publicKey(): string {
+    return this._keypair.publicKey();
+  }
+ 
+  /**
+   * Simulate the transaction to obtain the Soroban footprint, sign the
+   * prepared transaction, and return the signed XDR envelope as base-64.
+   *
+   * Steps:
+   *   1. `server.prepareTransaction(tx)` — attaches footprint + auth entries.
+   *   2. `preparedTx.sign(keypair)` — ECDSA/Ed25519 signature applied.
+   *   3. Returns `preparedTx.toEnvelope().toXDR("base64")`.
+   *
+   * @param tx     - Unsigned transaction with at least one Soroban operation
+   * @param server - Soroban RPC server used for simulation
+   * @returns Signed base-64 XDR envelope ready for `server.sendTransaction()`
+   *
+   * @throws {Error} When Soroban simulation fails (contract error, bad auth,
+   *   resource limit exceeded, etc.)
+   */
+  async signTransaction(
+    tx: Transaction,
+    server: SorobanRpc.Server
+  ): Promise<string> {
+    // Step 1: simulate → get footprint
+    const preparedTx = await server.prepareTransaction(tx);
+ 
+    Iif (SorobanRpc.Api.isSimulationError(preparedTx as any)) {
+      throw new Error(
+        `Soroban simulation failed: ${(preparedTx as any).error}`
+      );
+    }
+ 
+    // Step 2: sign
+    (preparedTx as Transaction).sign(this._keypair);
+ 
+    // Step 3: serialise
+    return (preparedTx as Transaction).toEnvelope().toXDR("base64");
+  }
+ 
+  // --------------------------------------------------------------------------
+  // Convenience
+  // --------------------------------------------------------------------------
+ 
+  /**
+   * Expose the underlying keypair for use-cases that need raw sign/verify
+   * access (e.g. building multi-sig transactions).
+   *
+   * Treat the returned keypair as read-only; do not call `keypair.sign()`
+   * directly on transaction envelopes — use `signTransaction()` so the
+   * simulation step is always executed.
+   */
+  get keypair(): Keypair {
+    return this._keypair;
+  }
+ 
+  /**
+   * Create a KeypairSigner from a secret key stored in an environment
+   * variable.
+   *
+   * ```ts
+   * const signer = KeypairSigner.fromEnv("LP_SECRET_KEY");
+   * ```
+   *
+   * @param envVar - Name of the environment variable holding the secret key
+   * @throws {Error} When the environment variable is not set
+   */
+  static fromEnv(envVar: string): KeypairSigner {
+    const secret = process.env[envVar];
+    Iif (!secret) {
+      throw new Error(
+        `KeypairSigner.fromEnv: environment variable "${envVar}" is not set`
+      );
+    }
+    // fromEnv is the recommended pattern — no warning needed
+    const kp = Keypair.fromSecret(secret);
+    return new KeypairSigner(kp);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/signers/index.html b/sdk/coverage/lcov-report/src/signers/index.html new file mode 100644 index 00000000..6ae048f8 --- /dev/null +++ b/sdk/coverage/lcov-report/src/signers/index.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for src/signers + + + + + + + + + +
+
+

All files src/signers

+
+ +
+ 0% + Statements + 0/90 +
+ + +
+ 0% + Branches + 0/45 +
+ + +
+ 0% + Functions + 0/23 +
+ + +
+ 0% + Lines + 0/88 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
FreighterSigner.d.ts +
+
0%0/00%0/00%0/00%0/0
FreighterSigner.ts +
+
0%0/660%0/360%0/160%0/65
ISigner.d.ts +
+
0%0/00%0/00%0/00%0/0
KeypairSigner.d.ts +
+
0%0/00%0/00%0/00%0/0
KeypairSigner.ts +
+
0%0/240%0/90%0/70%0/23
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/types.d.ts.html b/sdk/coverage/lcov-report/src/types.d.ts.html new file mode 100644 index 00000000..0a35d5f5 --- /dev/null +++ b/sdk/coverage/lcov-report/src/types.d.ts.html @@ -0,0 +1,343 @@ + + + + + + Code coverage report for src/types.d.ts + + + + + + + + + +
+
+

All files / src types.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Options for the fundInvoice() SDK method.
+ */
+export interface FundOptions {
+    /**
+     * When true, the SDK will reject funding if the oracle price feed is stale
+     * or unavailable. Defaults to false.
+     */
+    requireOracleVerification?: boolean;
+    /**
+     * Called when the LP's current token allowance is less than the invoice
+     * amount and an approval transaction is about to be built.
+     *
+     * @param params.requiredAmount  - Amount that needs to be approved (in token base units)
+     * @param params.currentAllowance - Current allowance the contract holds
+     */
+    onApprovalRequired?: (params: {
+        requiredAmount: bigint;
+        currentAllowance: bigint;
+    }) => void;
+    /**
+     * Called immediately after the approval transaction has been submitted to
+     * the network (before confirmation).
+     *
+     * @param params.approveTxHash - Hash of the submitted approval transaction
+     */
+    onApprovalSent?: (params: {
+        approveTxHash: string;
+    }) => void;
+    /**
+     * Called after the fund_invoice contract call has been simulated and the
+     * transaction is ready to sign and submit.
+     *
+     * @param params.effectiveYieldBps - Annualised yield in basis points derived
+     *   from the invoice's discount rate and time-to-due-date
+     * @param params.invoiceId         - The invoice being funded
+     */
+    onFunded?: (params: {
+        effectiveYieldBps: number;
+        invoiceId: bigint;
+    }) => void;
+}
+/**
+ * Return value of a successful fundInvoice() call.
+ */
+export interface FundResult {
+    /** Hash of the fund_invoice transaction. */
+    txHash: string;
+    /**
+     * Annualised effective yield in basis points for this funding position.
+     * Derived from discountRate × daysToMaturity / 365.
+     */
+    effectiveYieldBps: number;
+}
+/**
+ * Minimal view of an invoice returned by get_invoice().
+ */
+export interface InvoiceView {
+    id: bigint;
+    /** Token contract address used for this invoice. */
+    token: string;
+    /** Full invoice amount in token base units. */
+    amount: bigint;
+    /** Unix timestamp (seconds) when payment is due. */
+    dueDate: number;
+    /** Discount rate in basis points (e.g. 300 = 3.00 %). */
+    discountRate: number;
+    /** Current lifecycle status string. */
+    status: string;
+}
+/** Allowance query parameters. */
+export interface AllowanceParams {
+    /** Token contract address (SEP-41 / SAC). */
+    tokenAddress: string;
+    /** Address of the token owner (the LP). */
+    owner: string;
+    /** Address that will spend the tokens (the invoice-liquidity contract). */
+    spender: string;
+}
+/** Result of an allowance check. */
+export interface AllowanceResult {
+    /** Current approved amount in token base units. */
+    amount: bigint;
+    /** Ledger sequence at which the allowance expires (0 = no expiry stored). */
+    expirationLedger: number;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/types/governance.d.ts.html b/sdk/coverage/lcov-report/src/types/governance.d.ts.html new file mode 100644 index 00000000..ee7a52ce --- /dev/null +++ b/sdk/coverage/lcov-report/src/types/governance.d.ts.html @@ -0,0 +1,286 @@ + + + + + + Code coverage report for src/types/governance.d.ts + + + + + + + + + +
+
+

All files / src/types governance.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Governance types for the ILN SDK.
+ *
+ * Mirrors the on-chain governance contract's proposal model so TypeScript
+ * integrators can create proposals, vote and execute without hand-rolling
+ * Soroban calls.
+ */
+/**
+ * The set of parameter-changing actions a proposal can request.
+ *
+ * The numeric values match the contract's `ProposalAction` enum discriminants
+ * and are used directly as the `u32` argument when encoding the call.
+ */
+export declare enum ProposalAction {
+    /** Update the protocol fee, in basis points. */
+    UpdateProtocolFee = 0,
+    /** Update the minimum payer reputation required to submit an invoice. */
+    UpdateMinReputation = 1,
+    /** Update the oracle contract address (value is an address index/handle). */
+    UpdateOracle = 2,
+    /** Pause the contract (proposedValue ignored). */
+    PauseContract = 3,
+    /** Unpause the contract (proposedValue ignored). */
+    UnpauseContract = 4,
+    /** Update the default grace period, in seconds. */
+    UpdateGracePeriod = 5
+}
+/** Lifecycle status of a proposal. */
+export declare enum ProposalStatus {
+    Active = "Active",
+    Passed = "Passed",
+    Rejected = "Rejected",
+    Executed = "Executed"
+}
+/** A governance proposal as returned by the contract. */
+export interface Proposal {
+    /** Unique proposal identifier. */
+    id: bigint;
+    /** The parameter-changing action this proposal requests. */
+    action: ProposalAction;
+    /** The proposed new value for the action's parameter. */
+    proposedValue: bigint;
+    /** Hex-encoded 32-byte hash of the off-chain proposal description. */
+    descriptionHash: string;
+    /** Address that created the proposal. */
+    proposer: string;
+    /** Total weight of votes in support. */
+    votesFor: bigint;
+    /** Total weight of votes against. */
+    votesAgainst: bigint;
+    /** Current lifecycle status. */
+    status: ProposalStatus;
+    /** Unix timestamp (seconds) when voting closes. */
+    votingEndsAt: number;
+}
+/** Optional filter for {@link listProposals}. */
+export interface ProposalFilter {
+    /** Only return proposals in this status. */
+    status?: ProposalStatus;
+    /** Only return proposals created by this address. */
+    proposer?: string;
+}
+/** Result of creating a proposal. */
+export interface CreateProposalResult {
+    proposalId: bigint;
+    txHash: string;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/types/governance.ts.html b/sdk/coverage/lcov-report/src/types/governance.ts.html new file mode 100644 index 00000000..bb2455a5 --- /dev/null +++ b/sdk/coverage/lcov-report/src/types/governance.ts.html @@ -0,0 +1,301 @@ + + + + + + Code coverage report for src/types/governance.ts + + + + + + + + + +
+
+

All files / src/types governance.ts

+
+ +
+ 0% + Statements + 0/12 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Governance types for the ILN SDK.
+ *
+ * Mirrors the on-chain governance contract's proposal model so TypeScript
+ * integrators can create proposals, vote and execute without hand-rolling
+ * Soroban calls.
+ */
+ 
+/**
+ * The set of parameter-changing actions a proposal can request.
+ *
+ * The numeric values match the contract's `ProposalAction` enum discriminants
+ * and are used directly as the `u32` argument when encoding the call.
+ */
+export enum ProposalAction {
+  /** Update the protocol fee, in basis points. */
+  UpdateProtocolFee = 0,
+  /** Update the minimum payer reputation required to submit an invoice. */
+  UpdateMinReputation = 1,
+  /** Update the oracle contract address (value is an address index/handle). */
+  UpdateOracle = 2,
+  /** Pause the contract (proposedValue ignored). */
+  PauseContract = 3,
+  /** Unpause the contract (proposedValue ignored). */
+  UnpauseContract = 4,
+  /** Update the default grace period, in seconds. */
+  UpdateGracePeriod = 5,
+}
+ 
+/** Lifecycle status of a proposal. */
+export enum ProposalStatus {
+  Active = "Active",
+  Passed = "Passed",
+  Rejected = "Rejected",
+  Executed = "Executed",
+}
+ 
+/** A governance proposal as returned by the contract. */
+export interface Proposal {
+  /** Unique proposal identifier. */
+  id: bigint;
+  /** The parameter-changing action this proposal requests. */
+  action: ProposalAction;
+  /** The proposed new value for the action's parameter. */
+  proposedValue: bigint;
+  /** Hex-encoded 32-byte hash of the off-chain proposal description. */
+  descriptionHash: string;
+  /** Address that created the proposal. */
+  proposer: string;
+  /** Total weight of votes in support. */
+  votesFor: bigint;
+  /** Total weight of votes against. */
+  votesAgainst: bigint;
+  /** Current lifecycle status. */
+  status: ProposalStatus;
+  /** Unix timestamp (seconds) when voting closes. */
+  votingEndsAt: number;
+}
+ 
+/** Optional filter for {@link listProposals}. */
+export interface ProposalFilter {
+  /** Only return proposals in this status. */
+  status?: ProposalStatus;
+  /** Only return proposals created by this address. */
+  proposer?: string;
+}
+ 
+/** Result of creating a proposal. */
+export interface CreateProposalResult {
+  proposalId: bigint;
+  txHash: string;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/types/index.html b/sdk/coverage/lcov-report/src/types/index.html new file mode 100644 index 00000000..cd180a7b --- /dev/null +++ b/sdk/coverage/lcov-report/src/types/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/types + + + + + + + + + +
+
+

All files src/types

+
+ +
+ 0% + Statements + 0/12 +
+ + +
+ 0% + Branches + 0/4 +
+ + +
+ 0% + Functions + 0/2 +
+ + +
+ 0% + Lines + 0/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
governance.d.ts +
+
0%0/00%0/00%0/00%0/0
governance.ts +
+
0%0/120%0/40%0/20%0/12
invoice.d.ts +
+
0%0/00%0/00%0/00%0/0
params.d.ts +
+
0%0/00%0/00%0/00%0/0
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/types/invoice.d.ts.html b/sdk/coverage/lcov-report/src/types/invoice.d.ts.html new file mode 100644 index 00000000..312b7478 --- /dev/null +++ b/sdk/coverage/lcov-report/src/types/invoice.d.ts.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for src/types/invoice.d.ts + + + + + + + + + +
+
+

All files / src/types invoice.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export type InvoiceStatus = 'Pending' | 'Funded' | 'PartiallyFunded' | 'Paid' | 'Defaulted' | 'Appealed' | 'Disputed' | 'Expired' | 'Cancelled';
+export interface Invoice {
+    id: bigint;
+    freelancer: string;
+    payer: string;
+    token: string;
+    amount: bigint;
+    dueDate: number;
+    discountRate: number;
+    status: InvoiceStatus;
+    funder?: string;
+    fundedAt?: number;
+    amountFunded: bigint;
+    amountPaid: bigint;
+    referralCode?: string;
+    submitterReputation: number;
+    effectiveYieldBps: number;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/types/params.d.ts.html b/sdk/coverage/lcov-report/src/types/params.d.ts.html new file mode 100644 index 00000000..3a0d365e --- /dev/null +++ b/sdk/coverage/lcov-report/src/types/params.d.ts.html @@ -0,0 +1,139 @@ + + + + + + Code coverage report for src/types/params.d.ts + + + + + + + + + +
+
+

All files / src/types params.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export type SupportedToken = 'USDC' | 'EURC' | 'XLM' | string;
+export interface SubmitInvoiceParams {
+    payer: string;
+    amount: bigint;
+    token: SupportedToken;
+    discountRate: number;
+    dueDate: Date | number;
+    referralCode?: string;
+}
+export interface SubmitInvoiceResult {
+    invoiceId: bigint;
+    txHash: string;
+}
+export interface MarkPaidResult {
+    txHash: string;
+    remainingBalance: bigint;
+    fullySettled: boolean;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/utils/allowance.d.ts.html b/sdk/coverage/lcov-report/src/utils/allowance.d.ts.html new file mode 100644 index 00000000..bed7f462 --- /dev/null +++ b/sdk/coverage/lcov-report/src/utils/allowance.d.ts.html @@ -0,0 +1,256 @@ + + + + + + Code coverage report for src/utils/allowance.d.ts + + + + + + + + + +
+
+

All files / src/utils allowance.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Allowance utilities for SEP-41 / Stellar Asset Contract tokens.
+ *
+ * Abstracts the "check allowance → approve if needed" pattern so callers
+ * (e.g. fundInvoice) don't need to deal with raw XDR or Soroban operation
+ * building directly.
+ */
+import { SorobanRpc, Account } from "@stellar/stellar-sdk";
+import type { AllowanceParams, AllowanceResult } from "../types.js";
+/**
+ * Query the current SEP-41 token allowance granted by `owner` to `spender`.
+ *
+ * Calls `allowance(from, spender)` on the token contract and decodes the
+ * return value. Both the struct form `{ amount, expiration_ledger }` (SEP-41)
+ * and plain `i128` (older SAC) are handled.
+ *
+ * @param server         - Soroban RPC server instance
+ * @param params         - Token address, owner, and spender addresses
+ * @param sourceAccount  - Account used as the simulation source (sequence consumed)
+ * @returns AllowanceResult with `amount` (bigint) and `expirationLedger`
+ *
+ * @throws When the RPC simulation returns an error response
+ */
+export declare function getAllowance(server: SorobanRpc.Server, params: AllowanceParams, sourceAccount: Account): Promise<AllowanceResult>;
+/**
+ * Build a prepared (but unsigned) `approve` transaction envelope for a
+ * SEP-41 token contract.
+ *
+ * The returned base64-XDR string must be signed by the token owner's keypair
+ * before submission.
+ *
+ * Expiration is set to `currentLedger + 720` (≈ 1 hour at ~2s/ledger).
+ *
+ * @param server             - Soroban RPC server instance
+ * @param tokenAddress       - Token contract address
+ * @param ownerAccount       - Account object for the token owner (the LP)
+ * @param spenderAddress     - Address to approve (the invoice-liquidity contract)
+ * @param amount             - Amount to approve in token base units
+ * @param networkPassphrase  - Stellar network passphrase (defaults to TESTNET)
+ * @returns Base64-encoded XDR of the prepared transaction envelope
+ *
+ * @throws When the Soroban RPC `prepareTransaction` call fails
+ */
+export declare function buildApproveTransaction(server: SorobanRpc.Server, tokenAddress: string, ownerAccount: Account, spenderAddress: string, amount: bigint, networkPassphrase?: string): Promise<string>;
+/**
+ * Returns `true` when the given allowance satisfies both requirements:
+ *   1. `allowance.amount >= required`
+ *   2. The allowance will not expire before `minExpirationLedger` (when
+ *      provided). An `expirationLedger` of `0` is treated as "no expiry
+ *      stored" and always passes the expiry check.
+ *
+ * @param allowance           - Current allowance from getAllowance()
+ * @param required            - Minimum amount needed (in token base units)
+ * @param minExpirationLedger - Optional: require the allowance to remain
+ *                              valid at least until this ledger sequence
+ */
+export declare function isAllowanceSufficient(allowance: AllowanceResult, required: bigint, minExpirationLedger?: number): boolean;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/utils/allowance.ts.html b/sdk/coverage/lcov-report/src/utils/allowance.ts.html new file mode 100644 index 00000000..adcd8091 --- /dev/null +++ b/sdk/coverage/lcov-report/src/utils/allowance.ts.html @@ -0,0 +1,619 @@ + + + + + + Code coverage report for src/utils/allowance.ts + + + + + + + + + +
+
+

All files / src/utils allowance.ts

+
+ +
+ 0% + Statements + 0/25 +
+ + +
+ 0% + Branches + 0/14 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 0% + Lines + 0/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Allowance utilities for SEP-41 / Stellar Asset Contract tokens.
+ *
+ * Abstracts the "check allowance → approve if needed" pattern so callers
+ * (e.g. fundInvoice) don't need to deal with raw XDR or Soroban operation
+ * building directly.
+ */
+ 
+import {
+  Contract,
+  SorobanRpc,
+  TransactionBuilder,
+  Networks,
+  BASE_FEE,
+  scValToNative,
+  nativeToScVal,
+  Address,
+  Account,
+} from "@stellar/stellar-sdk";
+import type { AllowanceParams, AllowanceResult } from "../types.js";
+ 
+// ---------------------------------------------------------------------------
+// getAllowance
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Query the current SEP-41 token allowance granted by `owner` to `spender`.
+ *
+ * Calls `allowance(from, spender)` on the token contract and decodes the
+ * return value. Both the struct form `{ amount, expiration_ledger }` (SEP-41)
+ * and plain `i128` (older SAC) are handled.
+ *
+ * @param server         - Soroban RPC server instance
+ * @param params         - Token address, owner, and spender addresses
+ * @param sourceAccount  - Account used as the simulation source (sequence consumed)
+ * @returns AllowanceResult with `amount` (bigint) and `expirationLedger`
+ *
+ * @throws When the RPC simulation returns an error response
+ */
+export async function getAllowance(
+  server: SorobanRpc.Server,
+  params: AllowanceParams,
+  sourceAccount: Account
+): Promise<AllowanceResult> {
+  const tokenContract = new Contract(params.tokenAddress);
+ 
+  const op = tokenContract.call(
+    "allowance",
+    new Address(params.owner).toScVal(),
+    new Address(params.spender).toScVal()
+  );
+ 
+  const tx = new TransactionBuilder(sourceAccount, {
+    fee: BASE_FEE,
+    networkPassphrase: Networks.TESTNET,
+  })
+    .addOperation(op)
+    .setTimeout(30)
+    .build();
+ 
+  const simResult = await server.simulateTransaction(tx);
+ 
+  Iif (SorobanRpc.Api.isSimulationError(simResult)) {
+    throw new Error(`Allowance simulation failed: ${simResult.error}`);
+  }
+ 
+  Iif (!simResult.result?.retval) {
+    return { amount: 0n, expirationLedger: 0 };
+  }
+ 
+  const native = scValToNative(simResult.result.retval);
+ 
+  // SEP-41: allowance returns { amount: i128, expiration_ledger: u32 }
+  Iif (typeof native === "object" && native !== null && "amount" in native) {
+    const obj = native as Record<string, unknown>;
+    return {
+      amount: BigInt(String(obj["amount"])),
+      expirationLedger: Number(obj["expiration_ledger"] ?? 0),
+    };
+  }
+ 
+  // Older SAC: plain i128
+  return {
+    amount: BigInt(String(native)),
+    expirationLedger: 0,
+  };
+}
+ 
+// ---------------------------------------------------------------------------
+// buildApproveTransaction
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Build a prepared (but unsigned) `approve` transaction envelope for a
+ * SEP-41 token contract.
+ *
+ * The returned base64-XDR string must be signed by the token owner's keypair
+ * before submission.
+ *
+ * Expiration is set to `currentLedger + 720` (≈ 1 hour at ~2s/ledger).
+ *
+ * @param server             - Soroban RPC server instance
+ * @param tokenAddress       - Token contract address
+ * @param ownerAccount       - Account object for the token owner (the LP)
+ * @param spenderAddress     - Address to approve (the invoice-liquidity contract)
+ * @param amount             - Amount to approve in token base units
+ * @param networkPassphrase  - Stellar network passphrase (defaults to TESTNET)
+ * @returns Base64-encoded XDR of the prepared transaction envelope
+ *
+ * @throws When the Soroban RPC `prepareTransaction` call fails
+ */
+export async function buildApproveTransaction(
+  server: SorobanRpc.Server,
+  tokenAddress: string,
+  ownerAccount: Account,
+  spenderAddress: string,
+  amount: bigint,
+  networkPassphrase: string = Networks.TESTNET
+): Promise<string> {
+  const tokenContract = new Contract(tokenAddress);
+ 
+  // expiration_ledger ≈ now + 1 hour (720 ledgers @ ~5s/ledger)
+  const ledgerInfo = await server.getLatestLedger();
+  const expirationLedger = ledgerInfo.sequence + 720;
+ 
+  const op = tokenContract.call(
+    "approve",
+    new Address(ownerAccount.accountId()).toScVal(),
+    new Address(spenderAddress).toScVal(),
+    nativeToScVal(amount, { type: "i128" }),
+    nativeToScVal(expirationLedger, { type: "u32" })
+  );
+ 
+  const tx = new TransactionBuilder(ownerAccount, {
+    fee: BASE_FEE,
+    networkPassphrase,
+  })
+    .addOperation(op)
+    .setTimeout(30)
+    .build();
+ 
+  const preparedTx = await server.prepareTransaction(tx);
+  return (preparedTx as any).toEnvelope().toXDR("base64");
+}
+ 
+// ---------------------------------------------------------------------------
+// isAllowanceSufficient
+// ---------------------------------------------------------------------------
+ 
+/**
+ * Returns `true` when the given allowance satisfies both requirements:
+ *   1. `allowance.amount >= required`
+ *   2. The allowance will not expire before `minExpirationLedger` (when
+ *      provided). An `expirationLedger` of `0` is treated as "no expiry
+ *      stored" and always passes the expiry check.
+ *
+ * @param allowance           - Current allowance from getAllowance()
+ * @param required            - Minimum amount needed (in token base units)
+ * @param minExpirationLedger - Optional: require the allowance to remain
+ *                              valid at least until this ledger sequence
+ */
+export function isAllowanceSufficient(
+  allowance: AllowanceResult,
+  required: bigint,
+  minExpirationLedger?: number
+): boolean {
+  Iif (allowance.amount < required) return false;
+ 
+  Iif (
+    minExpirationLedger !== undefined &&
+    allowance.expirationLedger > 0 &&
+    allowance.expirationLedger < minExpirationLedger
+  ) {
+    return false;
+  }
+ 
+  return true;
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/utils/index.html b/sdk/coverage/lcov-report/src/utils/index.html new file mode 100644 index 00000000..88fe31f0 --- /dev/null +++ b/sdk/coverage/lcov-report/src/utils/index.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for src/utils + + + + + + + + + +
+
+

All files src/utils

+
+ +
+ 0% + Statements + 0/75 +
+ + +
+ 0% + Branches + 0/42 +
+ + +
+ 0% + Functions + 0/14 +
+ + +
+ 0% + Lines + 0/74 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
allowance.d.ts +
+
0%0/00%0/00%0/00%0/0
allowance.ts +
+
0%0/250%0/140%0/30%0/24
tokenRegistry.ts +
+
0%0/130%0/20%0/60%0/13
validate.d.ts +
+
0%0/00%0/00%0/00%0/0
validate.ts +
+
0%0/370%0/260%0/50%0/37
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/utils/tokenRegistry.ts.html b/sdk/coverage/lcov-report/src/utils/tokenRegistry.ts.html new file mode 100644 index 00000000..17c17c37 --- /dev/null +++ b/sdk/coverage/lcov-report/src/utils/tokenRegistry.ts.html @@ -0,0 +1,445 @@ + + + + + + Code coverage report for src/utils/tokenRegistry.ts + + + + + + + + + +
+
+

All files / src/utils tokenRegistry.ts

+
+ +
+ 0% + Statements + 0/13 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 0% + Functions + 0/6 +
+ + +
+ 0% + Lines + 0/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * TokenRegistry — centralised multi-token metadata for the ILN SDK (issue #227).
+ *
+ * Provides contract addresses, decimal precision, and minimum amounts
+ * for supported tokens on Stellar testnet and mainnet.
+ */
+ 
+export type NetworkName = "testnet" | "mainnet";
+ 
+export interface TokenInfo {
+  /** Token symbol (e.g. "USDC"). */
+  symbol: string;
+  /** Stellar contract address (SAC or SEP-41) for the given network. */
+  contractAddress: string;
+  /** Number of decimal places used by the token (e.g. 7 for USDC on Stellar). */
+  decimals: number;
+  /** Minimum meaningful amount in base units (to guard against dust). */
+  minimumAmount: bigint;
+}
+ 
+/** Built-in token registry entries per network. */
+const REGISTRY: Record<NetworkName, Record<string, TokenInfo>> = {
+  testnet: {
+    USDC: {
+      symbol: "USDC",
+      contractAddress: "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA",
+      decimals: 7,
+      minimumAmount: 1_000_000n, // 0.1 USDC
+    },
+    EURC: {
+      symbol: "EURC",
+      contractAddress: "GB3Q6QDZYTHWT7E5PVS3W7FUT5GVAFC5KSZFFLPU25GO575XC74F3X6U",
+      decimals: 7,
+      minimumAmount: 1_000_000n,
+    },
+    XLM: {
+      symbol: "XLM",
+      contractAddress: "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
+      decimals: 7,
+      minimumAmount: 10_000_000n, // 1 XLM
+    },
+  },
+  mainnet: {
+    USDC: {
+      symbol: "USDC",
+      contractAddress: "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75",
+      decimals: 7,
+      minimumAmount: 1_000_000n,
+    },
+    EURC: {
+      symbol: "EURC",
+      contractAddress: "CDTKPWPLOURQA2SGTKTUQOWRCBZEORB4BWBOMJ3D3ZTQQSGE5F6JBQLV",
+      decimals: 7,
+      minimumAmount: 1_000_000n,
+    },
+    XLM: {
+      symbol: "XLM",
+      contractAddress: "CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA",
+      decimals: 7,
+      minimumAmount: 10_000_000n,
+    },
+  },
+};
+ 
+export class TokenRegistry {
+  private readonly network: NetworkName;
+ 
+  constructor(network: NetworkName = "testnet") {
+    this.network = network;
+  }
+ 
+  /**
+   * Look up a token by symbol.
+   * @throws {Error} when the symbol is not found for the current network.
+   */
+  get(symbol: string): TokenInfo {
+    const entry = REGISTRY[this.network][symbol.toUpperCase()];
+    Iif (!entry) {
+      throw new Error(
+        `Token "${symbol}" is not registered for network "${this.network}". ` +
+          `Supported: ${Object.keys(REGISTRY[this.network]).join(", ")}`
+      );
+    }
+    return entry;
+  }
+ 
+  /** Returns all registered tokens for the current network. */
+  list(): TokenInfo[] {
+    return Object.values(REGISTRY[this.network]);
+  }
+ 
+  /**
+   * Register a custom token at runtime (e.g. project-specific SAC tokens).
+   * Custom entries override built-ins for the same symbol.
+   */
+  register(info: TokenInfo): void {
+    REGISTRY[this.network][info.symbol.toUpperCase()] = info;
+  }
+ 
+  /**
+   * Convert a human-readable amount to base units.
+   * @example registry.toBaseUnits("USDC", 10.5) // 105_000_000n
+   */
+  toBaseUnits(symbol: string, humanAmount: number): bigint {
+    const { decimals } = this.get(symbol);
+    return BigInt(Math.round(humanAmount * 10 ** decimals));
+  }
+ 
+  /**
+   * Convert base units back to a human-readable number.
+   * @example registry.fromBaseUnits("USDC", 105_000_000n) // 10.5
+   */
+  fromBaseUnits(symbol: string, baseAmount: bigint): number {
+    const { decimals } = this.get(symbol);
+    return Number(baseAmount) / 10 ** decimals;
+  }
+}
+ 
+/** Default singleton — testnet. Swap via `new TokenRegistry("mainnet")`. */
+export const tokenRegistry = new TokenRegistry("testnet");
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/utils/validate.d.ts.html b/sdk/coverage/lcov-report/src/utils/validate.d.ts.html new file mode 100644 index 00000000..e6306bd4 --- /dev/null +++ b/sdk/coverage/lcov-report/src/utils/validate.d.ts.html @@ -0,0 +1,265 @@ + + + + + + Code coverage report for src/utils/validate.d.ts + + + + + + + + + +
+
+

All files / src/utils validate.d.ts

+
+ +
+ 0% + Statements + 0/0 +
+ + +
+ 0% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/0 +
+ + +
+ 0% + Lines + 0/0 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Centralised input validation utilities for the ILN SDK.
+ *
+ * Validation logic for Stellar G-addresses, contract IDs, amounts, discount
+ * rates and due dates was previously duplicated across method implementations.
+ * Concentrating it here keeps error messages consistent and reduces bugs.
+ *
+ * Each validator throws a typed {@link ILNError} on failure and returns `void`
+ * on success, so they can be used as guard clauses at the top of methods.
+ */
+import type { SupportedToken } from "../types/params.js";
+/** Minimum allowed discount rate in basis points. */
+export declare const MIN_DISCOUNT_BPS = 1;
+/** Maximum allowed discount rate in basis points (50%). */
+export declare const MAX_DISCOUNT_BPS = 5000;
+/** Minimum invoice duration: 24 hours from now. */
+export declare const MIN_DUE_DATE_MS: number;
+/** Maximum invoice duration: 365 days from now. */
+export declare const MAX_DUE_DATE_MS: number;
+/**
+ * Validate a Stellar account (G…) address.
+ *
+ * @param address - The address to validate
+ * @throws {ILNError.InvalidAddress} If the address is empty, not a string, does
+ *   not start with `G`, or is not 56 characters long.
+ */
+export declare function validateGAddress(address: string): void;
+/**
+ * Validate a Soroban contract (C…) address.
+ *
+ * @param contractId - The contract ID to validate
+ * @throws {ILNError.InvalidAddress} If the contract ID is malformed.
+ */
+export declare function validateContractId(contractId: string): void;
+/**
+ * Validate a token amount against a minimum and the token's precision.
+ *
+ * @param amount - The amount in token base units
+ * @param min    - The minimum allowed amount (inclusive) in base units
+ * @param token  - The token the amount is denominated in
+ * @throws {ILNError.InvalidAmount} If the amount is not a positive integer, is
+ *   below the minimum, or exceeds the token's precision.
+ */
+export declare function validateAmount(amount: bigint, min: bigint, token: SupportedToken): void;
+/**
+ * Validate a discount rate.
+ *
+ * @param rate - Discount rate in basis points (1–5000)
+ * @throws {ILNError.InvalidDiscountRate} If the rate is outside the 1–5000 bps range.
+ */
+export declare function validateDiscountRate(rate: number): void;
+/**
+ * Validate an invoice due date.
+ *
+ * @param date - The due date
+ * @throws {ILNError.InvalidDueDate} If the date is invalid.
+ * @throws {ILNError.DueDateTooSoon} If the date is less than 24h from now.
+ * @throws {ILNError.DueDateTooFar} If the date is more than 365 days from now.
+ */
+export declare function validateDueDate(date: Date): void;
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov-report/src/utils/validate.ts.html b/sdk/coverage/lcov-report/src/utils/validate.ts.html new file mode 100644 index 00000000..802afc26 --- /dev/null +++ b/sdk/coverage/lcov-report/src/utils/validate.ts.html @@ -0,0 +1,532 @@ + + + + + + Code coverage report for src/utils/validate.ts + + + + + + + + + +
+
+

All files / src/utils validate.ts

+
+ +
+ 0% + Statements + 0/37 +
+ + +
+ 0% + Branches + 0/26 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 0% + Lines + 0/37 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Centralised input validation utilities for the ILN SDK.
+ *
+ * Validation logic for Stellar G-addresses, contract IDs, amounts, discount
+ * rates and due dates was previously duplicated across method implementations.
+ * Concentrating it here keeps error messages consistent and reduces bugs.
+ *
+ * Each validator throws a typed {@link ILNError} on failure and returns `void`
+ * on success, so they can be used as guard clauses at the top of methods.
+ */
+ 
+import { ILNError } from "../errors.js";
+import type { SupportedToken } from "../types/params.js";
+ 
+/** Length of a Stellar StrKey-encoded public key (G…) address. */
+const G_ADDRESS_LENGTH = 56;
+/** Length of a Stellar StrKey-encoded contract (C…) address. */
+const C_ADDRESS_LENGTH = 56;
+ 
+/** Minimum allowed discount rate in basis points. */
+export const MIN_DISCOUNT_BPS = 1;
+/** Maximum allowed discount rate in basis points (50%). */
+export const MAX_DISCOUNT_BPS = 5000;
+ 
+/** Minimum invoice duration: 24 hours from now. */
+export const MIN_DUE_DATE_MS = 24 * 60 * 60 * 1000;
+/** Maximum invoice duration: 365 days from now. */
+export const MAX_DUE_DATE_MS = 365 * 24 * 60 * 60 * 1000;
+ 
+/** Base-unit precision (decimals) for each supported token. */
+const TOKEN_DECIMALS: Record<string, number> = {
+  USDC: 7,
+  EURC: 7,
+  XLM: 7,
+};
+ 
+/**
+ * Validate a Stellar account (G…) address.
+ *
+ * @param address - The address to validate
+ * @throws {ILNError.InvalidAddress} If the address is empty, not a string, does
+ *   not start with `G`, or is not 56 characters long.
+ */
+export function validateGAddress(address: string): void {
+  Iif (typeof address !== "string" || address.length === 0) {
+    throw new ILNError.InvalidAddress("Address must be a non-empty string");
+  }
+  Iif (!address.startsWith("G")) {
+    throw new ILNError.InvalidAddress(
+      `Invalid Stellar address "${address}": must start with "G"`
+    );
+  }
+  Iif (address.length !== G_ADDRESS_LENGTH) {
+    throw new ILNError.InvalidAddress(
+      `Invalid Stellar address "${address}": must be ${G_ADDRESS_LENGTH} characters`
+    );
+  }
+}
+ 
+/**
+ * Validate a Soroban contract (C…) address.
+ *
+ * @param contractId - The contract ID to validate
+ * @throws {ILNError.InvalidAddress} If the contract ID is malformed.
+ */
+export function validateContractId(contractId: string): void {
+  Iif (typeof contractId !== "string" || contractId.length === 0) {
+    throw new ILNError.InvalidAddress("Contract ID must be a non-empty string");
+  }
+  Iif (!contractId.startsWith("C") || contractId.length !== C_ADDRESS_LENGTH) {
+    throw new ILNError.InvalidAddress(
+      `Invalid contract ID "${contractId}": must start with "C" and be ${C_ADDRESS_LENGTH} characters`
+    );
+  }
+}
+ 
+/**
+ * Validate a token amount against a minimum and the token's precision.
+ *
+ * @param amount - The amount in token base units
+ * @param min    - The minimum allowed amount (inclusive) in base units
+ * @param token  - The token the amount is denominated in
+ * @throws {ILNError.InvalidAmount} If the amount is not a positive integer, is
+ *   below the minimum, or exceeds the token's precision.
+ */
+export function validateAmount(
+  amount: bigint,
+  min: bigint,
+  token: SupportedToken
+): void {
+  Iif (typeof amount !== "bigint") {
+    throw new ILNError.InvalidAmount("Amount must be a bigint (token base units)");
+  }
+  Iif (amount <= 0n) {
+    throw new ILNError.InvalidAmount("Amount must be greater than 0");
+  }
+  Iif (amount < min) {
+    throw new ILNError.InvalidAmount(
+      `Amount ${amount} is below the minimum of ${min} for ${token}`
+    );
+  }
+  // Precision guard: amounts are integers in base units, so a negative or
+  // unknown decimal config is the only way this can be violated. We surface
+  // unsupported tokens explicitly to avoid silent mis-scaling.
+  const decimals = TOKEN_DECIMALS[token];
+  Iif (decimals === undefined && !token.startsWith("C")) {
+    throw new ILNError.InvalidAmount(
+      `Unknown token "${token}": cannot verify amount precision`
+    );
+  }
+}
+ 
+/**
+ * Validate a discount rate.
+ *
+ * @param rate - Discount rate in basis points (1–5000)
+ * @throws {ILNError.InvalidDiscountRate} If the rate is outside the 1–5000 bps range.
+ */
+export function validateDiscountRate(rate: number): void {
+  Iif (!Number.isInteger(rate)) {
+    throw new ILNError.InvalidDiscountRate("Discount rate must be an integer (bps)");
+  }
+  Iif (rate < MIN_DISCOUNT_BPS || rate > MAX_DISCOUNT_BPS) {
+    throw new ILNError.InvalidDiscountRate(
+      `Discount rate must be between ${MIN_DISCOUNT_BPS} and ${MAX_DISCOUNT_BPS} bps`
+    );
+  }
+}
+ 
+/**
+ * Validate an invoice due date.
+ *
+ * @param date - The due date
+ * @throws {ILNError.InvalidDueDate} If the date is invalid.
+ * @throws {ILNError.DueDateTooSoon} If the date is less than 24h from now.
+ * @throws {ILNError.DueDateTooFar} If the date is more than 365 days from now.
+ */
+export function validateDueDate(date: Date): void {
+  Iif (!(date instanceof Date) || Number.isNaN(date.getTime())) {
+    throw new ILNError.InvalidDueDate("Due date must be a valid Date");
+  }
+  const delta = date.getTime() - Date.now();
+  Iif (delta < MIN_DUE_DATE_MS) {
+    throw new ILNError.DueDateTooSoon("Due date must be at least 24 hours from now");
+  }
+  Iif (delta > MAX_DUE_DATE_MS) {
+    throw new ILNError.DueDateTooFar("Due date must be within 365 days from now");
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/sdk/coverage/lcov.info b/sdk/coverage/lcov.info new file mode 100644 index 00000000..a9e1046d --- /dev/null +++ b/sdk/coverage/lcov.info @@ -0,0 +1,1109 @@ +TN: +SF:src/client.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/client.test.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/client.ts +FN:92,(anonymous_0) +FN:114,(anonymous_1) +FN:142,(anonymous_2) +FN:167,(anonymous_3) +FN:183,(anonymous_4) +FN:200,(anonymous_5) +FN:228,(anonymous_6) +FN:231,(anonymous_7) +FN:236,(anonymous_8) +FN:245,(anonymous_9) +FN:249,(anonymous_10) +FNF:11 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +DA:31,0 +DA:36,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:118,0 +DA:148,0 +DA:168,0 +DA:186,0 +DA:187,0 +DA:190,0 +DA:203,0 +DA:204,0 +DA:207,0 +DA:229,0 +DA:232,0 +DA:237,0 +DA:238,0 +DA:242,0 +DA:246,0 +DA:250,0 +DA:254,0 +LF:23 +LH:0 +BRDA:119,0,0,0 +BRDA:119,0,1,0 +BRDA:122,1,0,0 +BRDA:122,1,1,0 +BRDA:149,2,0,0 +BRDA:149,2,1,0 +BRDA:152,3,0,0 +BRDA:152,3,1,0 +BRDA:186,4,0,0 +BRDA:203,5,0,0 +BRDA:237,6,0,0 +BRF:11 +BRH:0 +end_of_record +TN: +SF:src/errors.ts +FN:2,(anonymous_0) +FN:48,(anonymous_1) +FN:7,(anonymous_2) +FN:8,(anonymous_3) +FN:9,(anonymous_4) +FN:10,(anonymous_5) +FN:11,(anonymous_6) +FN:12,(anonymous_7) +FN:13,(anonymous_8) +FN:14,(anonymous_9) +FN:15,(anonymous_10) +FN:16,(anonymous_11) +FN:17,(anonymous_12) +FN:18,(anonymous_13) +FN:19,(anonymous_14) +FN:20,(anonymous_15) +FN:21,(anonymous_16) +FN:22,(anonymous_17) +FN:23,(anonymous_18) +FN:24,(anonymous_19) +FN:25,(anonymous_20) +FN:26,(anonymous_21) +FN:27,(anonymous_22) +FN:28,(anonymous_23) +FN:29,(anonymous_24) +FN:30,(anonymous_25) +FN:31,(anonymous_26) +FN:32,(anonymous_27) +FN:33,(anonymous_28) +FN:34,(anonymous_29) +FN:35,(anonymous_30) +FN:36,(anonymous_31) +FN:37,(anonymous_32) +FN:38,(anonymous_33) +FN:39,(anonymous_34) +FN:40,(anonymous_35) +FN:41,(anonymous_36) +FN:42,(anonymous_37) +FN:43,(anonymous_38) +FN:44,(anonymous_39) +FN:45,(anonymous_40) +FN:46,(anonymous_41) +FNF:42 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:0,(anonymous_17) +FNDA:0,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_22) +FNDA:0,(anonymous_23) +FNDA:0,(anonymous_24) +FNDA:0,(anonymous_25) +FNDA:0,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:0,(anonymous_28) +FNDA:0,(anonymous_29) +FNDA:0,(anonymous_30) +FNDA:0,(anonymous_31) +FNDA:0,(anonymous_32) +FNDA:0,(anonymous_33) +FNDA:0,(anonymous_34) +FNDA:0,(anonymous_35) +FNDA:0,(anonymous_36) +FNDA:0,(anonymous_37) +FNDA:0,(anonymous_38) +FNDA:0,(anonymous_39) +FNDA:0,(anonymous_40) +FNDA:0,(anonymous_41) +DA:2,0 +DA:3,0 +DA:4,0 +DA:7,0 +DA:8,0 +DA:9,0 +DA:10,0 +DA:11,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:93,0 +LF:86 +LH:0 +BRDA:51,0,0,0 +BRDA:53,1,0,0 +BRDA:53,1,1,0 +BRDA:53,1,2,0 +BRDA:53,1,3,0 +BRDA:53,1,4,0 +BRDA:53,1,5,0 +BRDA:53,1,6,0 +BRDA:53,1,7,0 +BRDA:53,1,8,0 +BRDA:53,1,9,0 +BRDA:53,1,10,0 +BRDA:53,1,11,0 +BRDA:53,1,12,0 +BRDA:53,1,13,0 +BRDA:53,1,14,0 +BRDA:53,1,15,0 +BRDA:53,1,16,0 +BRDA:53,1,17,0 +BRDA:53,1,18,0 +BRDA:53,1,19,0 +BRDA:53,1,20,0 +BRDA:53,1,21,0 +BRDA:53,1,22,0 +BRDA:53,1,23,0 +BRDA:53,1,24,0 +BRDA:53,1,25,0 +BRDA:53,1,26,0 +BRDA:53,1,27,0 +BRDA:53,1,28,0 +BRDA:53,1,29,0 +BRDA:53,1,30,0 +BRDA:53,1,31,0 +BRDA:53,1,32,0 +BRDA:53,1,33,0 +BRDA:53,1,34,0 +BRDA:53,1,35,0 +BRDA:53,1,36,0 +BRDA:7,2,0,0 +BRDA:8,3,0,0 +BRDA:9,4,0,0 +BRDA:10,5,0,0 +BRDA:11,6,0,0 +BRDA:12,7,0,0 +BRDA:13,8,0,0 +BRDA:14,9,0,0 +BRDA:15,10,0,0 +BRDA:16,11,0,0 +BRDA:17,12,0,0 +BRDA:18,13,0,0 +BRDA:19,14,0,0 +BRDA:20,15,0,0 +BRDA:21,16,0,0 +BRDA:22,17,0,0 +BRDA:23,18,0,0 +BRDA:24,19,0,0 +BRDA:25,20,0,0 +BRDA:26,21,0,0 +BRDA:27,22,0,0 +BRDA:28,23,0,0 +BRDA:29,24,0,0 +BRDA:30,25,0,0 +BRDA:31,26,0,0 +BRDA:32,27,0,0 +BRDA:33,28,0,0 +BRDA:34,29,0,0 +BRDA:35,30,0,0 +BRDA:36,31,0,0 +BRDA:37,32,0,0 +BRDA:38,33,0,0 +BRDA:39,34,0,0 +BRDA:40,35,0,0 +BRDA:41,36,0,0 +BRDA:42,37,0,0 +BRDA:43,38,0,0 +BRDA:44,39,0,0 +BRDA:45,40,0,0 +BRDA:46,41,0,0 +BRF:78 +BRH:0 +end_of_record +TN: +SF:src/index.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/types.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/events/subscribe.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/events/types.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/cancelInvoice.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/fundInvoice.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/governance.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/markPaid.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/queries.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/queries.ts +FN:30,getInvoice +FN:102,listInvoicesBySubmitter +FN:137,(anonymous_2) +FN:176,listInvoicesByLP +FN:211,(anonymous_4) +FNF:5 +FNH:0 +FNDA:0,getInvoice +FNDA:0,listInvoicesBySubmitter +FNDA:0,(anonymous_2) +FNDA:0,listInvoicesByLP +FNDA:0,(anonymous_4) +DA:37,0 +DA:38,0 +DA:43,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:111,0 +DA:112,0 +DA:119,0 +DA:127,0 +DA:129,0 +DA:130,0 +DA:132,0 +DA:133,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:185,0 +DA:186,0 +DA:193,0 +DA:201,0 +DA:203,0 +DA:204,0 +DA:206,0 +DA:207,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:213,0 +DA:214,0 +LF:40 +LH:0 +BRDA:53,0,0,0 +BRDA:54,1,0,0 +BRDA:54,2,0,0 +BRDA:54,2,1,0 +BRDA:59,3,0,0 +BRDA:75,4,0,0 +BRDA:75,4,1,0 +BRDA:76,5,0,0 +BRDA:76,5,1,0 +BRDA:77,6,0,0 +BRDA:77,6,1,0 +BRDA:80,7,0,0 +BRDA:80,7,1,0 +BRDA:108,8,0,0 +BRDA:109,9,0,0 +BRDA:129,10,0,0 +BRDA:132,11,0,0 +BRDA:148,12,0,0 +BRDA:148,12,1,0 +BRDA:149,13,0,0 +BRDA:149,13,1,0 +BRDA:150,14,0,0 +BRDA:150,14,1,0 +BRDA:153,15,0,0 +BRDA:153,15,1,0 +BRDA:182,16,0,0 +BRDA:183,17,0,0 +BRDA:203,18,0,0 +BRDA:206,19,0,0 +BRDA:222,20,0,0 +BRDA:222,20,1,0 +BRDA:223,21,0,0 +BRDA:223,21,1,0 +BRDA:224,22,0,0 +BRDA:224,22,1,0 +BRDA:227,23,0,0 +BRDA:227,23,1,0 +BRF:37 +BRH:0 +end_of_record +TN: +SF:src/methods/reputation.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/reputation.ts +FN:49,isValidGAddress +FN:78,getReputation +FNF:2 +FNH:0 +FNDA:0,isValidGAddress +FNDA:0,getReputation +DA:47,0 +DA:50,0 +DA:84,0 +DA:85,0 +DA:90,0 +DA:91,0 +DA:96,0 +DA:101,0 +DA:109,0 +DA:111,0 +DA:112,0 +DA:116,0 +DA:117,0 +DA:126,0 +DA:128,0 +LF:15 +LH:0 +BRDA:82,0,0,0 +BRDA:84,1,0,0 +BRDA:111,2,0,0 +BRDA:116,3,0,0 +BRDA:129,4,0,0 +BRDA:129,4,1,0 +BRDA:130,5,0,0 +BRDA:130,5,1,0 +BRDA:131,6,0,0 +BRDA:131,6,1,0 +BRDA:132,7,0,0 +BRDA:132,7,1,0 +BRDA:133,8,0,0 +BRDA:133,8,1,0 +BRF:14 +BRH:0 +end_of_record +TN: +SF:src/methods/stats.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/stats.ts +FN:69,getContractStats +FNF:1 +FNH:0 +FNDA:0,getContractStats +DA:74,0 +DA:75,0 +DA:77,0 +DA:82,0 +DA:90,0 +DA:92,0 +DA:93,0 +DA:96,0 +DA:97,0 +DA:109,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:120,0 +LF:16 +LH:0 +BRDA:72,0,0,0 +BRDA:92,1,0,0 +BRDA:96,2,0,0 +BRDA:114,3,0,0 +BRDA:121,4,0,0 +BRDA:121,4,1,0 +BRDA:122,5,0,0 +BRDA:122,5,1,0 +BRDA:123,6,0,0 +BRDA:123,6,1,0 +BRDA:124,7,0,0 +BRDA:124,7,1,0 +BRDA:125,8,0,0 +BRDA:125,8,1,0 +BRDA:126,9,0,0 +BRDA:126,9,1,0 +BRDA:129,10,0,0 +BRDA:129,10,1,0 +BRF:18 +BRH:0 +end_of_record +TN: +SF:src/methods/submitInvoice.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/methods/transferLPPosition.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/signers/FreighterSigner.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/signers/FreighterSigner.ts +FN:63,(anonymous_0) +FN:69,(anonymous_1) +FN:76,(anonymous_2) +FN:83,(anonymous_3) +FN:90,(anonymous_4) +FN:99,(anonymous_5) +FN:152,(anonymous_6) +FN:168,(anonymous_7) +FN:181,(anonymous_8) +FN:220,(anonymous_9) +FN:272,(anonymous_10) +FN:277,(anonymous_11) +FN:286,(anonymous_12) +FN:296,(anonymous_13) +FN:306,(anonymous_14) +FN:327,(anonymous_15) +FNF:16 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +DA:64,0 +DA:65,0 +DA:66,0 +DA:70,0 +DA:77,0 +DA:84,0 +DA:91,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:111,0 +DA:116,0 +DA:144,0 +DA:145,0 +DA:153,0 +DA:169,0 +DA:182,0 +DA:184,0 +DA:186,0 +DA:191,0 +DA:193,0 +DA:194,0 +DA:198,0 +DA:200,0 +DA:201,0 +DA:202,0 +DA:225,0 +DA:226,0 +DA:230,0 +DA:232,0 +DA:233,0 +DA:239,0 +DA:244,0 +DA:245,0 +DA:246,0 +DA:252,0 +DA:253,0 +DA:257,0 +DA:260,0 +DA:261,0 +DA:264,0 +DA:273,0 +DA:278,0 +DA:289,0 +DA:290,0 +DA:291,0 +DA:297,0 +DA:299,0 +DA:308,0 +DA:309,0 +DA:312,0 +DA:315,0 +DA:316,0 +DA:318,0 +DA:319,0 +DA:328,0 +DA:330,0 +DA:332,0 +DA:338,0 +DA:341,0 +DA:345,0 +DA:348,0 +LF:65 +LH:0 +BRDA:99,0,0,0 +BRDA:99,0,1,0 +BRDA:169,1,0,0 +BRDA:169,1,1,0 +BRDA:184,2,0,0 +BRDA:193,3,0,0 +BRDA:193,4,0,0 +BRDA:193,4,1,0 +BRDA:225,5,0,0 +BRDA:232,6,0,0 +BRDA:245,7,0,0 +BRDA:260,8,0,0 +BRDA:260,9,0,0 +BRDA:260,9,1,0 +BRDA:278,10,0,0 +BRDA:278,10,1,0 +BRDA:290,11,0,0 +BRDA:290,12,0,0 +BRDA:290,12,1,0 +BRDA:316,13,0,0 +BRDA:318,14,0,0 +BRDA:328,15,0,0 +BRDA:328,15,1,0 +BRDA:328,16,0,0 +BRDA:328,16,1,0 +BRDA:332,17,0,0 +BRDA:333,18,0,0 +BRDA:333,18,1,0 +BRDA:333,18,2,0 +BRDA:333,18,3,0 +BRDA:341,19,0,0 +BRDA:342,20,0,0 +BRDA:342,20,1,0 +BRDA:342,20,2,0 +BRDA:348,21,0,0 +BRDA:348,21,1,0 +BRF:36 +BRH:0 +end_of_record +TN: +SF:src/signers/ISigner.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/signers/KeypairSigner.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/signers/KeypairSigner.ts +FN:33,isTestEnvironment +FN:48,warnIfHardcodedSecret +FN:101,(anonymous_2) +FN:115,(anonymous_3) +FN:135,(anonymous_4) +FN:167,(anonymous_5) +FN:182,(anonymous_6) +FNF:7 +FNH:0 +FNDA:0,isTestEnvironment +FNDA:0,warnIfHardcodedSecret +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +DA:34,0 +DA:49,0 +DA:52,0 +DA:57,0 +DA:58,0 +DA:62,0 +DA:66,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:106,0 +DA:116,0 +DA:140,0 +DA:142,0 +DA:143,0 +DA:149,0 +DA:152,0 +DA:168,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:190,0 +DA:191,0 +LF:23 +LH:0 +BRDA:35,0,0,0 +BRDA:35,0,1,0 +BRDA:35,0,2,0 +BRDA:49,1,0,0 +BRDA:57,2,0,0 +BRDA:102,3,0,0 +BRDA:102,3,1,0 +BRDA:142,4,0,0 +BRDA:184,5,0,0 +BRF:9 +BRH:0 +end_of_record +TN: +SF:src/types/governance.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/types/governance.ts +FN:15,(anonymous_0) +FN:31,(anonymous_1) +FNF:2 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +DA:15,0 +DA:17,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:25,0 +DA:27,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +LF:12 +LH:0 +BRDA:15,0,0,0 +BRDA:15,0,1,0 +BRDA:31,1,0,0 +BRDA:31,1,1,0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:src/types/invoice.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/types/params.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/utils/allowance.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/utils/allowance.ts +FN:40,getAllowance +FN:112,buildApproveTransaction +FN:162,isAllowanceSufficient +FNF:3 +FNH:0 +FNDA:0,getAllowance +FNDA:0,buildApproveTransaction +FNDA:0,isAllowanceSufficient +DA:45,0 +DA:47,0 +DA:53,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:67,0 +DA:68,0 +DA:71,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:83,0 +DA:120,0 +DA:123,0 +DA:124,0 +DA:126,0 +DA:134,0 +DA:142,0 +DA:143,0 +DA:167,0 +DA:169,0 +DA:174,0 +DA:177,0 +LF:24 +LH:0 +BRDA:63,0,0,0 +BRDA:67,1,0,0 +BRDA:74,2,0,0 +BRDA:74,3,0,0 +BRDA:74,3,1,0 +BRDA:74,3,2,0 +BRDA:78,4,0,0 +BRDA:78,4,1,0 +BRDA:118,5,0,0 +BRDA:167,6,0,0 +BRDA:169,7,0,0 +BRDA:170,8,0,0 +BRDA:170,8,1,0 +BRDA:170,8,2,0 +BRF:14 +BRH:0 +end_of_record +TN: +SF:src/utils/tokenRegistry.ts +FN:68,(anonymous_0) +FN:76,(anonymous_1) +FN:88,(anonymous_2) +FN:96,(anonymous_3) +FN:104,(anonymous_4) +FN:113,(anonymous_5) +FNF:6 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:22,0 +DA:69,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:84,0 +DA:89,0 +DA:97,0 +DA:105,0 +DA:106,0 +DA:114,0 +DA:115,0 +DA:120,0 +LF:13 +LH:0 +BRDA:68,0,0,0 +BRDA:78,1,0,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:src/utils/validate.d.ts +FNF:0 +FNH:0 +LF:0 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/utils/validate.ts +FN:44,validateGAddress +FN:66,validateContractId +FN:86,validateAmount +FN:119,validateDiscountRate +FN:138,validateDueDate +FNF:5 +FNH:0 +FNDA:0,validateGAddress +FNDA:0,validateContractId +FNDA:0,validateAmount +FNDA:0,validateDiscountRate +FNDA:0,validateDueDate +DA:16,0 +DA:18,0 +DA:21,0 +DA:23,0 +DA:26,0 +DA:28,0 +DA:31,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:53,0 +DA:54,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:91,0 +DA:92,0 +DA:94,0 +DA:95,0 +DA:97,0 +DA:98,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:120,0 +DA:121,0 +DA:123,0 +DA:124,0 +DA:139,0 +DA:140,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:146,0 +DA:147,0 +LF:37 +LH:0 +BRDA:45,0,0,0 +BRDA:45,1,0,0 +BRDA:45,1,1,0 +BRDA:48,2,0,0 +BRDA:53,3,0,0 +BRDA:67,4,0,0 +BRDA:67,5,0,0 +BRDA:67,5,1,0 +BRDA:70,6,0,0 +BRDA:70,7,0,0 +BRDA:70,7,1,0 +BRDA:91,8,0,0 +BRDA:94,9,0,0 +BRDA:97,10,0,0 +BRDA:106,11,0,0 +BRDA:106,12,0,0 +BRDA:106,12,1,0 +BRDA:120,13,0,0 +BRDA:123,14,0,0 +BRDA:123,15,0,0 +BRDA:123,15,1,0 +BRDA:139,16,0,0 +BRDA:139,17,0,0 +BRDA:139,17,1,0 +BRDA:143,18,0,0 +BRDA:146,19,0,0 +BRF:26 +BRH:0 +end_of_record diff --git a/tests/e2e/lifecycle.test.ts b/tests/e2e/lifecycle.test.ts new file mode 100644 index 00000000..b82519db --- /dev/null +++ b/tests/e2e/lifecycle.test.ts @@ -0,0 +1,188 @@ +import { Account, Keypair, Horizon, SorobanRpc } from "@stellar/stellar-sdk"; +import { ILNClient } from "../../sdk/src/client.js"; +import { submitInvoice } from "../../sdk/src/methods/submitInvoice.js"; +import { fundInvoice } from "../../sdk/src/methods/fundInvoice.js"; +import { markPaid } from "../../sdk/src/methods/markPaid.js"; +import { getInvoice } from "../../sdk/src/methods/queries.js"; +import { subscribe } from "../../sdk/src/events/subscribe.js"; +import { createApp } from "../../indexer/src/app.js"; +import { getDb } from "../../indexer/src/database/db.js"; +import { initializeSchema } from "../../indexer/src/database/schema.js"; +import request from "supertest"; +import type Database from "better-sqlite3"; +import type { Server } from "http"; + +const TEST_SUBMITTER_SECRET = process.env.TEST_SUBMITTER_SECRET || "SAX33OJKWNZK2KW6F7TNEZ4EEX4MXQ4P6V7T2JZ4W6XAJXN3NKCBJQPL"; +const TEST_LP_SECRET = process.env.TEST_LP_SECRET || "SCD2Q6M76VFLHNHDNROENMX7PJ5OBYBMVPM73S4M6XAJXN3NKCBJQPL"; +const NETWORK_PASSPHRASE = "Test SDF Network ; September 2015"; +const HORIZON_URL = "https://horizon-testnet.stellar.org"; +const RPC_URL = "https://soroban-testnet.stellar.org"; +const CONTRACT_ID = "CD2Q6M76VFLHNHDNROENMX7PJ5OBYBMVPM73S4M6XAJXN3NKCBJQPLUC"; + +describe("E2E - Full Invoice Lifecycle", () => { + let db: Database.Database; + let appServer: Server; + let unsubscribeEvents: () => void; + const horizon = new Horizon.Server(HORIZON_URL); + const server = new SorobanRpc.Server(RPC_URL); + + const submitter = Keypair.fromSecret(TEST_SUBMITTER_SECRET); + const lp = Keypair.fromSecret(TEST_LP_SECRET); + + beforeAll(async () => { + // Start indexer database and app + db = getDb(":memory:"); + initializeSchema(db); + const app = createApp(db); + appServer = app.listen(3001); + + // Set up mock subscription that writes to SQLite to simulate indexer database updates + unsubscribeEvents = subscribe( + horizon, + CONTRACT_ID, + {}, + (event) => { + try { + if (event.type === "submitted") { + db.prepare( + `INSERT INTO invoices (id, freelancer, payer, token, amount, due_date, discount_rate, status, created_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)` + ).run( + Number(event.invoiceId), + event.freelancer, + event.payer, + event.token, + String(event.amount), + Number(event.dueDate), + event.discountRate, + "Pending", + Math.floor(Date.now() / 1000) + ); + db.prepare( + `INSERT INTO events (invoice_id, event_type, ledger, timestamp, data) + VALUES (?, ?, ?, ?, ?)` + ).run(Number(event.invoiceId), "submitted", 100, Math.floor(Date.now() / 1000), JSON.stringify(event)); + } else if (event.type === "funded") { + db.prepare( + `UPDATE invoices + SET status = 'Funded', funder = ?, funded_at = ?, amount_funded = ? + WHERE id = ?` + ).run(event.funder, Math.floor(Date.now() / 1000), String(event.amountFunded), Number(event.invoiceId)); + db.prepare( + `INSERT INTO events (invoice_id, event_type, ledger, timestamp, data) + VALUES (?, ?, ?, ?, ?)` + ).run(Number(event.invoiceId), "funded", 100, Math.floor(Date.now() / 1000), JSON.stringify(event)); + } else if (event.type === "paid") { + db.prepare( + `UPDATE invoices + SET status = 'Paid', amount_paid = ? + WHERE id = ?` + ).run(String(event.amountPaid), Number(event.invoiceId)); + db.prepare( + `INSERT INTO events (invoice_id, event_type, ledger, timestamp, data) + VALUES (?, ?, ?, ?, ?)` + ).run(Number(event.invoiceId), "paid", 100, Math.floor(Date.now() / 1000), JSON.stringify(event)); + } + } catch (err) { + console.error("Error processing contract event:", err); + } + } + ); + }, 10000); + + afterAll((done) => { + if (unsubscribeEvents) unsubscribeEvents(); + if (db) db.close(); + if (appServer) appServer.close(done); + else done(); + }); + + it("should successfully execute full invoice lifecycle and update indexer", async () => { + // This test runs only when integration secrets are provided + if (!process.env.TEST_SUBMITTER_SECRET || !process.env.TEST_LP_SECRET) { + console.log("Skipping E2E lifecycle test because TEST_SUBMITTER_SECRET or TEST_LP_SECRET is missing"); + return; + } + + const client = ILNClient.custom({ + rpcUrl: RPC_URL, + networkPassphrase: NETWORK_PASSPHRASE, + contractId: CONTRACT_ID, + }); + + const submitterRaw = await server.getAccount(submitter.publicKey()); + const submitterAccount = new Account(submitter.publicKey(), submitterRaw.sequenceNumber()); + + // 1. Submit Invoice + const dueDate = Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60; + const submitRes = await submitInvoice( + server, + CONTRACT_ID, + { + payer: lp.publicKey(), + amount: 1000000n, + token: "USDC", + discountRate: 300, + dueDate, + }, + submitterAccount, + async (tx) => { + const prepared = await server.prepareTransaction(tx); + prepared.sign(submitter); + return prepared; + }, + NETWORK_PASSPHRASE + ); + + const invoiceId = submitRes.invoiceId; + expect(invoiceId).toBeDefined(); + + // Verify status via SDK + let invoice = await getInvoice(server, CONTRACT_ID, invoiceId, submitterAccount, NETWORK_PASSPHRASE); + expect(invoice.status).toBe("Pending"); + + // Wait up to 10 seconds for indexer reflection + await new Promise((resolve) => setTimeout(resolve, 8000)); + let indexerRes = await request("http://localhost:3001").get(`/invoices/${invoiceId}`); + expect(indexerRes.status).toBe(200); + expect(indexerRes.body.status).toBe("Pending"); + + // 2. Fund Invoice + const lpRaw = await server.getAccount(lp.publicKey()); + const lpAccount = new Account(lp.publicKey(), lpRaw.sequenceNumber()); + await fundInvoice(server, CONTRACT_ID, lp, invoiceId, {}, NETWORK_PASSPHRASE); + + // Verify status via SDK + invoice = await getInvoice(server, CONTRACT_ID, invoiceId, lpAccount, NETWORK_PASSPHRASE); + expect(invoice.status).toBe("Funded"); + + // Wait for indexer reflection + await new Promise((resolve) => setTimeout(resolve, 8000)); + indexerRes = await request("http://localhost:3001").get(`/invoices/${invoiceId}`); + expect(indexerRes.body.status).toBe("Funded"); + + // 3. Pay Invoice + await markPaid( + server, + CONTRACT_ID, + invoiceId, + undefined, + lpAccount, + async (tx) => { + const prepared = await server.prepareTransaction(tx); + prepared.sign(lp); + return prepared; + }, + NETWORK_PASSPHRASE + ); + + // Verify status via SDK + invoice = await getInvoice(server, CONTRACT_ID, invoiceId, lpAccount, NETWORK_PASSPHRASE); + expect(invoice.status).toBe("Paid"); + + // Wait for indexer reflection + await new Promise((resolve) => setTimeout(resolve, 8000)); + indexerRes = await request("http://localhost:3001").get(`/invoices/${invoiceId}`); + expect(indexerRes.body.status).toBe("Paid"); + }, 240000); +}); diff --git a/tests/e2e/reputation.test.ts b/tests/e2e/reputation.test.ts new file mode 100644 index 00000000..2f690e32 --- /dev/null +++ b/tests/e2e/reputation.test.ts @@ -0,0 +1,65 @@ +import { createApp } from "../../indexer/src/app.js"; +import { getDb } from "../../indexer/src/database/db.js"; +import { initializeSchema } from "../../indexer/src/database/schema.js"; +import { seedReputation } from "../../indexer/tests/helpers.js"; +import request from "supertest"; +import type Database from "better-sqlite3"; +import type { Server } from "http"; + +describe("E2E - Reputation System Lifecycle", () => { + let db: Database.Database; + let appServer: Server; + + beforeAll(() => { + db = getDb(":memory:"); + initializeSchema(db); + const app = createApp(db); + appServer = app.listen(3002); + }); + + afterAll((done) => { + if (db) db.close(); + if (appServer) appServer.close(done); + else done(); + }); + + it("should reflect correct score and history for 5 paid invoices", async () => { + const address = "GBBB...PAYER1"; + seedReputation(db, { + address, + old_score: 0, + new_score: 100, + invoices_submitted: 5, + invoices_paid: 5, + invoices_defaulted: 0, + ledger: 100, + timestamp: Math.floor(Date.now() / 1000), + }); + + const res = await request("http://localhost:3002").get(`/reputation/${address}`); + expect(res.status).toBe(200); + expect(res.body.score).toBe(100); + expect(res.body.invoicesPaid).toBe(5); + expect(res.body.invoicesDefaulted).toBe(0); + }); + + it("should calculate score correctly after 3 submitted and 2 expired", async () => { + const address = "GBBB...PAYER2"; + seedReputation(db, { + address, + old_score: 0, + new_score: 33, + invoices_submitted: 3, + invoices_paid: 1, + invoices_defaulted: 2, + ledger: 200, + timestamp: Math.floor(Date.now() / 1000), + }); + + const res = await request("http://localhost:3002").get(`/reputation/${address}`); + expect(res.status).toBe(200); + expect(res.body.score).toBe(33); + expect(res.body.invoicesSubmitted).toBe(3); + expect(res.body.invoicesDefaulted).toBe(2); + }); +});