diff --git a/.direnv/flake-profile b/.direnv/flake-profile new file mode 120000 index 0000000..0c05709 --- /dev/null +++ b/.direnv/flake-profile @@ -0,0 +1 @@ +flake-profile-1-link \ No newline at end of file diff --git a/.direnv/flake-profile-1-link b/.direnv/flake-profile-1-link new file mode 120000 index 0000000..283ea47 --- /dev/null +++ b/.direnv/flake-profile-1-link @@ -0,0 +1 @@ +/nix/store/q61ni6s1mqr37fcp38wyzm5ryn82z26n-nix-shell-env \ No newline at end of file diff --git a/.gitignore b/.gitignore index db36602..24ef0f2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ fm_client_db .cargo .vscode .DS_Store +fm_db diff --git a/fedimint-clientd/src/main.rs b/fedimint-clientd/src/main.rs index 73d37c0..024c4b3 100644 --- a/fedimint-clientd/src/main.rs +++ b/fedimint-clientd/src/main.rs @@ -254,7 +254,7 @@ fn fedimint_v2_rest() -> Router { post(fedimint::ln::list_gateways::handle_rest), ); - let wallet_router = Router::new() + let onchain_router = Router::new() .route( "/deposit-address", post(fedimint::onchain::deposit_address::handle_rest), @@ -291,7 +291,7 @@ fn fedimint_v2_rest() -> Router { .nest("/admin", admin_router) .nest("/mint", mint_router) .nest("/ln", ln_router) - .nest("/wallet", wallet_router) + .nest("/onchain", onchain_router) } /// Implements Cashu V1 API Routes: diff --git a/flake.lock b/flake.lock index fd30016..112303e 100644 --- a/flake.lock +++ b/flake.lock @@ -77,11 +77,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1712730246, - "narHash": "sha256-iB8bFj+07RHpmt+XuGGvYQk2Iwm12u6+DklGq/+Tg5s=", + "lastModified": 1712903033, + "narHash": "sha256-KcvsEm0h1mIwBHFAzWFBjGihnbf2fxpAaXOdVbUfAI4=", "owner": "nix-community", "repo": "fenix", - "rev": "d402ae4a5e5676722290470f61a5e8e3155b5487", + "rev": "c739f83545e625227f4d0af7fe2a71e69931fa4c", "type": "github" }, "original": { @@ -95,11 +95,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1701680307, - "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -134,11 +134,11 @@ ] }, "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -177,11 +177,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1712437997, - "narHash": "sha256-g0whLLwRvgO2FsyhY8fNk+TWenS3jg5UdlWL4uqgFeo=", + "lastModified": 1712867921, + "narHash": "sha256-edTFV4KldkCMdViC/rmpJa7oLIU8SE/S35lh/ukC7bg=", "owner": "nixos", "repo": "nixpkgs", - "rev": "e38d7cb66ea4f7a0eb6681920615dfcc30fc2920", + "rev": "51651a540816273b67bc4dedea2d37d116c5f7fe", "type": "github" }, "original": { @@ -202,11 +202,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1712663608, - "narHash": "sha256-tN9ZL6kGppmHg84lxlpAlaN+kXWNctKK7Yitq/iXDEw=", + "lastModified": 1712818880, + "narHash": "sha256-VDxsvgj/bNypHq48tQWtc3VRbWvzlFjzKf9ZZIVO10Y=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "a5feb4f05f09adca661c869b1bf2324898cbaa43", + "rev": "657b33b0cb9bd49085202e91ad5b4676532c9140", "type": "github" }, "original": { diff --git a/misc/git-hooks/pre-commit b/misc/git-hooks/pre-commit index 7959e97..d21df26 100755 --- a/misc/git-hooks/pre-commit +++ b/misc/git-hooks/pre-commit @@ -9,13 +9,13 @@ set -e # Revert `git stash` on exit function revert_git_stash { - >&2 echo "Unstashing uncommitted changes..." + echo >&2 "Unstashing uncommitted changes..." git stash pop -q } # Stash pending changes and revert them when script ends if [ -z "${NO_STASH:-}" ] && [ $is_unclean -ne 0 ]; then - >&2 echo "Stashing uncommitted changes..." + echo >&2 "Stashing uncommitted changes..." GIT_LITERAL_PATHSPECS=0 git stash -q --keep-index trap revert_git_stash EXIT fi @@ -25,146 +25,145 @@ FLAKEBOX_GIT_LS="$(git ls-files)" export FLAKEBOX_GIT_LS_TEXT FLAKEBOX_GIT_LS_TEXT="$(echo "$FLAKEBOX_GIT_LS" | grep -v -E "\.(png|ods|jpg|jpeg|woff2|keystore|wasm|ttf|jar|ico|gif)\$")" - function check_nothing() { true } export -f check_nothing function check_cargo_fmt() { - set -euo pipefail + set -euo pipefail - flakebox-in-each-cargo-workspace cargo fmt --all --check + flakebox-in-each-cargo-workspace cargo fmt --all --check } export -f check_cargo_fmt function check_cargo_lock() { - set -euo pipefail + set -euo pipefail - # https://users.rust-lang.org/t/check-if-the-cargo-lock-is-up-to-date-without-building-anything/91048/5 - flakebox-in-each-cargo-workspace cargo update --workspace --locked + # https://users.rust-lang.org/t/check-if-the-cargo-lock-is-up-to-date-without-building-anything/91048/5 + flakebox-in-each-cargo-workspace cargo update --workspace --locked } export -f check_cargo_lock function check_leftover_dbg() { - set -euo pipefail - - errors="" - for path in $(echo "$FLAKEBOX_GIT_LS_TEXT" | grep '.*\.rs'); do - if grep 'dbg!(' "$path" > /dev/null; then - >&2 echo "$path contains dbg! macro" - errors="true" - fi - done - - if [ -n "$errors" ]; then - >&2 echo "Fix the problems above or use --no-verify" 1>&2 - return 1 + set -euo pipefail + + errors="" + for path in $(echo "$FLAKEBOX_GIT_LS_TEXT" | grep '.*\.rs'); do + if grep 'dbg!(' "$path" >/dev/null; then + echo >&2 "$path contains dbg! macro" + errors="true" fi + done + + if [ -n "$errors" ]; then + echo >&2 "Fix the problems above or use --no-verify" 1>&2 + return 1 + fi } export -f check_leftover_dbg function check_semgrep() { - set -euo pipefail + set -euo pipefail - # semgrep is not available on MacOS - if ! command -v semgrep > /dev/null ; then - >&2 echo "Skipping semgrep check: not available" - return 0 - fi + # semgrep is not available on MacOS + if ! command -v semgrep >/dev/null; then + echo >&2 "Skipping semgrep check: not available" + return 0 + fi - if [ ! -f .config/semgrep.yaml ] ; then - >&2 echo "Skipping semgrep check: .config/semgrep.yaml doesn't exist" - return 0 - fi + if [ ! -f .config/semgrep.yaml ]; then + echo >&2 "Skipping semgrep check: .config/semgrep.yaml doesn't exist" + return 0 + fi - if [ ! -s .config/semgrep.yaml ] ; then - >&2 echo "Skipping semgrep check: .config/semgrep.yaml empty" - return 0 - fi + if [ ! -s .config/semgrep.yaml ]; then + echo >&2 "Skipping semgrep check: .config/semgrep.yaml empty" + return 0 + fi - env SEMGREP_ENABLE_VERSION_CHECK=0 \ - semgrep -q --error --no-rewrite-rule-ids --config .config/semgrep.yaml + env SEMGREP_ENABLE_VERSION_CHECK=0 \ + semgrep -q --error --no-rewrite-rule-ids --config .config/semgrep.yaml } export -f check_semgrep function check_shellcheck() { - set -euo pipefail + set -euo pipefail - for path in $(echo "$FLAKEBOX_GIT_LS_TEXT" | grep -E '.*\.sh$'); do - shellcheck --severity=warning "$path" - done + for path in $(echo "$FLAKEBOX_GIT_LS_TEXT" | grep -E '.*\.sh$'); do + shellcheck --severity=warning "$path" + done } export -f check_shellcheck function check_trailing_newline() { - set -euo pipefail - - errors="" - for path in $(echo "$FLAKEBOX_GIT_LS_TEXT"); do - - # extra branches for clarity - if [ ! -s "$path" ]; then - # echo "$path is empty" - true - elif [ -z "$(tail -c 1 < "$path")" ]; then - # echo "$path ends with a newline or with a null byte" - true - else - >&2 echo "$path doesn't end with a newline" 1>&2 - errors="true" - fi - done - - if [ -n "$errors" ]; then - >&2 echo "Fix the problems above or use --no-verify" 1>&2 - return 1 + set -euo pipefail + + errors="" + for path in $(echo "$FLAKEBOX_GIT_LS_TEXT"); do + + # extra branches for clarity + if [ ! -s "$path" ]; then + # echo "$path is empty" + true + elif [ -z "$(tail -c 1 <"$path")" ]; then + # echo "$path ends with a newline or with a null byte" + true + else + echo >&2 "$path doesn't end with a newline" 1>&2 + errors="true" fi + done + + if [ -n "$errors" ]; then + echo >&2 "Fix the problems above or use --no-verify" 1>&2 + return 1 + fi } export -f check_trailing_newline function check_trailing_whitespace() { - set -euo pipefail - - rev="HEAD" - if ! git rev-parse -q 1>/dev/null HEAD 2>/dev/null ; then - >&2 echo "Warning: no commits yet, checking against --root" - rev="--root" - fi - if ! git diff --check $rev ; then - >&2 echo "Trailing whitespace detected. Please remove them before committing." - return 1 - fi + set -euo pipefail + + rev="HEAD" + if ! git rev-parse -q HEAD 1>/dev/null 2>/dev/null; then + echo >&2 "Warning: no commits yet, checking against --root" + rev="--root" + fi + if ! git diff --check $rev; then + echo >&2 "Trailing whitespace detected. Please remove them before committing." + return 1 + fi } export -f check_trailing_whitespace function check_typos() { - set -euo pipefail + set -euo pipefail - if ! echo "$FLAKEBOX_GIT_LS_TEXT" | typos --file-list - --force-exclude ; then - >&2 echo "Typos found: Valid new words can be added to '.typos.toml'" - return 1 - fi + if ! echo "$FLAKEBOX_GIT_LS_TEXT" | typos --file-list - --force-exclude; then + echo >&2 "Typos found: Valid new words can be added to '.typos.toml'" + return 1 + fi } export -f check_typos parallel \ --nonotice \ -::: \ - check_cargo_fmt \ - check_cargo_lock \ - check_leftover_dbg \ - check_semgrep \ - check_shellcheck \ - check_trailing_newline \ - check_trailing_whitespace \ - check_typos \ + ::: \ + check_cargo_fmt \ + check_cargo_lock \ + check_leftover_dbg \ + check_semgrep \ + check_shellcheck \ + check_trailing_newline \ + check_trailing_whitespace \ + check_typos \ check_nothing diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..bfcd84b --- /dev/null +++ b/shell.nix @@ -0,0 +1,6 @@ +# save this as shell.nix +{ pkgs ? import {}}: + +pkgs.mkShell { + packages = [ pkgs.hello ]; +} diff --git a/wrappers/fedimint-go/cmd/main.go b/wrappers/fedimint-go/cmd/main.go index 9b927ec..cfd198c 100644 --- a/wrappers/fedimint-go/cmd/main.go +++ b/wrappers/fedimint-go/cmd/main.go @@ -2,6 +2,7 @@ package main import ( "encoding/hex" + "encoding/json" "fedimint-go-client/pkg/fedimint" "fmt" "os" @@ -64,95 +65,480 @@ func buildTestClient() *fedimint.FedimintClient { } func main() { - client := buildTestClient() + fc := buildTestClient() + fc.UseDefaultGateway() keyPair := newKeyPair() - fmt.Println("Generated key pair: ", keyPair) + fmt.Printf("Generated Key Pair: ") + fmt.Printf(" Private Key: %s\n", keyPair.PrivateKey) + fmt.Printf(" Public Key: %s\n", keyPair.PublicKey) + + /////////////////// + // ADMIN METHODS // + /////////////////// - // ADMIN METHODS // `/v2/admin/config` logMethod("/v2/admin/config") - data, err := client.Config() + data, err := fc.Config() if err != nil { - fmt.Println("Error calling config: ", err) + fmt.Println("Error calling CONFIG: ", err) return } logInputAndOutput(nil, data) // `/v2/admin/discover-version` logMethod("/v2/admin/discover-version") - data, err = client.DiscoverVersion(1) + discoverResponseData, err := fc.DiscoverVersion(1) if err != nil { - fmt.Println("Error calling discoverVersion: ", err) + fmt.Println("Error calling VERSION: ", err) return } - logInputAndOutput(nil, data) - // `/v2/admin/federation-ids` + jsonBytes, err := json.Marshal(discoverResponseData) + if err != nil { + fmt.Println("Error marshaling JSON(discover-version):", err) + return + } + var fedimintResponseData interface{} + err = json.Unmarshal(jsonBytes, &fedimintResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(discover-version):", err) + return + } + + logInputAndOutput(1, fedimintResponseData) + + // `/v2/admin/federation-ids logMethod("/v2/admin/federation-ids") - federationIds, err := client.FederationIds() + federationIds, err := fc.FederationIds() if err != nil { - fmt.Println("Error calling federationIds: ", err) + fmt.Println("Error calling FEDERATION_IDS: ", err) return } logInputAndOutput(nil, federationIds) // `/v2/admin/info` logMethod("/v2/admin/info") - infoData, err := client.Info() + infoDataResponse, err := fc.Info() + if err != nil { + fmt.Println("Error calling INFO: ", err) + return + } + + jsonBytes, err = json.Marshal(infoDataResponse) + if err != nil { + fmt.Println("Error marshaling JSON(discover-version):", err) + return + } + var infoResponseData interface{} + err = json.Unmarshal(jsonBytes, &infoResponseData) if err != nil { - fmt.Println("Error calling info: ", err) + fmt.Println("Error unmarshalling JSON(discover-version):", err) return } - logInputAndOutput(nil, infoData) + + logInputAndOutput(nil, infoResponseData) // `/v2/admin/join` - inviteCode := os.Getenv("FEDIMINT_CLIENTD_INVITE_CODE") + inviteCode := os.Getenv("FEDIMINT_CLIENTD_BASE_URL") if inviteCode == "" { inviteCode = "fed11qgqrgvnhwden5te0v9k8q6rp9ekh2arfdeukuet595cr2ttpd3jhq6rzve6zuer9wchxvetyd938gcewvdhk6tcqqysptkuvknc7erjgf4em3zfh90kffqf9srujn6q53d6r056e4apze5cw27h75" } logMethod("/v2/admin/join") - joinData, err := client.Join(inviteCode, true, true, false) + joinData, err := fc.Join(inviteCode, true, true, false) if err != nil { - fmt.Println("Error calling join: ", err) + fmt.Println("Error calling JOIN: ", err) return } - logInputAndOutput(map[string]interface{}{"inviteCode": inviteCode}, joinData) + + jsonBytes, err = json.Marshal(joinData) + if err != nil { + fmt.Println("Error marshaling JSON(join):", err) + return + } + var joinResponseData interface{} + err = json.Unmarshal(jsonBytes, &joinResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(join):", err) + return + } + + logInputAndOutput(inviteCode, joinResponseData) // `/v2/admin/list-operations` logMethod("/v2/admin/list-operations") - listOperationsData, err := client.ListOperations(10, nil) + listOperationsData, err := fc.ListOperations(10, nil) if err != nil { - fmt.Println("Error calling listOperations: ", err) + fmt.Println("Error calling JOIN: ", err) return } - logInputAndOutput(map[string]interface{}{"limit": 10}, listOperationsData) - // LIGHTNING METHODS + jsonBytes, err = json.Marshal(listOperationsData) + if err != nil { + fmt.Println("Error marshaling JSON(list-operations):", err) + return + } + var listOperationsResponseData interface{} + err = json.Unmarshal(jsonBytes, &listOperationsResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(list-operations):", err) + return + } + + logInputAndOutput([]interface{}{10}, listOperationsResponseData) + + /////////////////////// + // LIGHTNING METHODS // + /////////////////////// + // `/v2/ln/list-gateways` logMethod("/v2/ln/list-gateways") - listGatewaysData, err := client.Ln.ListGateways() + gatewayList, err := fc.Ln.ListGateways(nil) + if err != nil { + fmt.Println("Error calling LIST_GATEWAYS: ", err) + return + } + + jsonBytes, err = json.Marshal(gatewayList) if err != nil { - fmt.Println("Error calling listGateways: ", err) + fmt.Println("Error marshaling JSON(list-gateways):", err) return } - logInputAndOutput(nil, listGatewaysData) + var gatewayListResponseData interface{} + err = json.Unmarshal(jsonBytes, &gatewayListResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(list-gateways):", err) + return + } + + logInputAndOutput(nil, gatewayListResponseData) // `/v2/ln/invoice` logMethod("/v2/ln/invoice") - invoiceData, err := client.Ln.CreateInvoice(10000, "test", nil, nil, nil) + invoiceData, err := fc.Ln.CreateInvoice(10000, "test", nil, nil, nil) if err != nil { - fmt.Println("Error calling createInvoice: ", err) + fmt.Println("Error calling INVOICE: ", err) return } - logInputAndOutput(map[string]interface{}{"amountMsat": 10000, "description": "test"}, invoiceData) + + jsonBytes, err = json.Marshal(invoiceData) + if err != nil { + fmt.Println("Error marshaling JSON(invoice):", err) + return + } + var invoiceResponseData interface{} + err = json.Unmarshal(jsonBytes, &invoiceResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(invoice):", err) + return + } + + logInputAndOutput([]interface{}{10000, "test_Invoice"}, invoiceResponseData) // `/v2/ln/pay` logMethod("/v2/ln/pay") - payData, err := client.Ln.Pay(invoiceData.Invoice, nil, nil, nil, nil) + payData, err := fc.Ln.Pay(invoiceData.Invoice, fc.GetActiveGatewayId(), nil, nil, nil) if err != nil { - fmt.Println("Error calling pay: ", err) + fmt.Println("Error calling PAY: ", err) return } - logInputAndOutput(map[string]interface{}{"paymentInfo": invoiceData.Invoice}, payData) + jsonBytes, err = json.Marshal(payData) + if err != nil { + fmt.Println("Error marshaling JSON(pay):", err) + return + } + var payResponseData interface{} + err = json.Unmarshal(jsonBytes, &payResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(pay):", err) + return + } + + logInputAndOutput(invoiceData.Invoice, payResponseData) + + // /v2/ln/await-invoice + logMethod("/v2/ln/await-invoice") + awaitInvoiceData, err := fc.Ln.AwaitInvoice(invoiceData.OperationId, fc.GetActiveGatewayId(), nil) + if err != nil { + fmt.Println("Error calling AWAIT_INVOICE: ", err) + return + } + + jsonBytes, err = json.Marshal(awaitInvoiceData) + if err != nil { + fmt.Println("Error marshaling JSON(await-invoice):", err) + return + } + var awaitInvoiceResponseData interface{} + err = json.Unmarshal(jsonBytes, &awaitInvoiceResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(await-invoice):", err) + return + } + + logInputAndOutput(invoiceData.OperationId, awaitInvoiceResponseData) + + // `/v1/ln/invoice-external-pubkey-tweaked` + logMethod("/v1/ln/invoice-external-pubkey-tweaked") + tweakInvoice, err := fc.Ln.CreateInvoiceForPubkeyTweak(keyPair.PublicKey, 1, 10000, "test", fc.GetActiveGatewayId(), nil, nil) + if err != nil { + fmt.Println("Error calling CREATE_INVOICE_FOR_PUBKEY_TWEAK: ", err) + return + } + + jsonBytes, err = json.Marshal(tweakInvoice) + if err != nil { + fmt.Println("Error marshaling JSON(await-invoice):", err) + return + } + var tweakInvoiceResponseData interface{} + err = json.Unmarshal(jsonBytes, &tweakInvoiceResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(await-invoice):", err) + return + } + + logInputAndOutput([]interface{}{keyPair.PublicKey, 1, 10000, "test"}, tweakInvoiceResponseData) + // pay the invoice + _, _ = fc.Ln.Pay(tweakInvoice.Invoice, fc.GetActiveGatewayId(), nil, nil, nil) + fmt.Println("Paid locked invoice!") + + // `/v1/ln/claim-external-pubkey-tweaked` + logMethod("/v1/ln/claim-external-pubkey-tweaked") + claimInvoice, err := fc.Ln.ClaimPubkeyTweakReceive(keyPair.PrivateKey, []uint64{1}, fc.GetActiveFederationId(), fc.GetActiveFederationId()) + if err != nil { + fmt.Println("Error calling CLAIM_PUBKEY_RECEIVE_TWEAKED: ", err) + return + } + + jsonBytes, err = json.Marshal(claimInvoice) + if err != nil { + fmt.Println("Error marshaling JSON(claim-external-pubkey-tweaked):", err) + return + } + var claimInvoiceResponseData interface{} + err = json.Unmarshal(jsonBytes, &claimInvoiceResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(claim-external-pubkey-tweaked):", err) + return + } + + logInputAndOutput([]interface{}{keyPair.PrivateKey, []uint64{1}}, claimInvoiceResponseData) + + ////////////////// + // MINT METHODS // + ////////////////// + + // `/v2/mint/spend` + logMethod("/v2/mint/spend") + mintData, err := fc.Mint.Spend(3000, true, 1000, false, nil) + if err != nil { + fmt.Println("Error calling SPEND: ", err) + return + } + + jsonBytes, err = json.Marshal(mintData) + if err != nil { + fmt.Println("Error marshaling JSON(spend):", err) + return + } + var mintResponseData interface{} + err = json.Unmarshal(jsonBytes, &mintResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(spend):", err) + return + } + + logInputAndOutput([]interface{}{3000, true, 1000}, mintResponseData) + + // `/v2/mint/decode-notes` + logMethod("/v2/mint/decode-notes") + decodedData, err := fc.Mint.DecodeNotes(mintData.Notes) + if err != nil { + fmt.Println("Error calling DECODE_NOTES: ", err) + return + } + + jsonBytes, err = json.Marshal(decodedData) + if err != nil { + fmt.Println("Error marshaling JSON(decode-notes):", err) + return + } + var decodedResponseData interface{} + err = json.Unmarshal(jsonBytes, &decodedResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(decode-notes):", err) + return + } + + logInputAndOutput(mintData.Notes, decodedResponseData) + + // `/v2/mint/encode-notes` + logMethod("/v2/mint/encode-notes") + encodedData, err := fc.Mint.EncodeNotes(decodedData.NotesJson) + if err != nil { + fmt.Println("Error calling DECODE_NOTES: ", err) + return + } + + jsonBytes, err = json.Marshal(encodedData) + if err != nil { + fmt.Println("Error marshaling JSON(encode-notes):", err) + return + } + var encodedResponseData interface{} + err = json.Unmarshal(jsonBytes, &encodedResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(encode-notes):", err) + return + } + + logInputAndOutput(decodedData.NotesJson, encodedResponseData) + + // `/v2/mint/validate` + logMethod("/v2/mint/validate") + validateData, err := fc.Mint.Validate(mintData.Notes, nil) + if err != nil { + fmt.Println("Error calling VALIDATE: ", err) + return + } + + jsonBytes, err = json.Marshal(validateData) + if err != nil { + fmt.Println("Error marshaling JSON(validate):", err) + return + } + var validateResponseData interface{} + err = json.Unmarshal(jsonBytes, &validateResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(validate):", err) + return + } + + logInputAndOutput(mintData.Notes, validateResponseData) + + // `/v2/mint/reissue` + logMethod("/v2/mint/reissue") + reissueData, err := fc.Mint.Reissue(mintData.Notes, nil) + if err != nil { + fmt.Println("Error calling REISSUE: ", err) + return + } + + jsonBytes, err = json.Marshal(reissueData) + if err != nil { + fmt.Println("Error marshaling JSON(reissue):", err) + return + } + var reissueResponseData interface{} + err = json.Unmarshal(jsonBytes, &reissueResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(reissue):", err) + return + } + + logInputAndOutput(mintData.Notes, reissueResponseData) + + // `/v2/mint/split` + logMethod("/v2/mint/split") + splitData, err := fc.Mint.Split(mintData.Notes) + if err != nil { + fmt.Println("Error calling SPLIT: ", err) + return + } + + jsonBytes, err = json.Marshal(splitData) + if err != nil { + fmt.Println("Error marshaling JSON(split):", err) + return + } + var splitResponseData interface{} + err = json.Unmarshal(jsonBytes, &splitResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(split):", err) + return + } + + logInputAndOutput(mintData.Notes, splitResponseData) + + // `/v2/mint/combine` + logMethod("/v2/mint/combine") + notesVec := func() []string { + result := make([]string, 0, len(splitData.Notes)) + for _, value := range splitData.Notes { + result = append(result, value) + } + return result + }() + combineData, err := fc.Mint.Combine(notesVec) + if err != nil { + fmt.Println("Error calling COMBINE: ", err) + return + } + + jsonBytes, err = json.Marshal(combineData) + if err != nil { + fmt.Println("Error marshaling JSON(split):", err) + return + } + var combineResponseData interface{} + err = json.Unmarshal(jsonBytes, &combineResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(split):", err) + return + } + + logInputAndOutput(splitData.Notes, combineResponseData) + + ///////////////////// + // ONCHAIN METHODS // + ///////////////////// + + // `/v2/onchain/deposit-address` + logMethod("/v2/onchain/deposit-address") + addr, err := fc.Onchain.CreateDepositAddress(1000, nil) + if err != nil { + fmt.Println("Error calling CREATE_DEPOSIT_ADDRESS: ", err) + return + } + + jsonBytes, err = json.Marshal(addr) + if err != nil { + fmt.Println("Error marshaling JSON(deposit-address):", err) + return + } + var addrResponseData interface{} + err = json.Unmarshal(jsonBytes, &addrResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(deposit-address):", err) + return + } + + logInputAndOutput(1000, addrResponseData) + + // `/v2/onchain/withdraw` + logMethod("/v2/onchain/withdraw") + withdrawData, err := fc.Onchain.Withdraw(addr.Address, 1000, nil) + if err != nil { + fmt.Println("Error calling WITHDRAW: ", err) + return + } + + jsonBytes, err = json.Marshal(withdrawData) + if err != nil { + fmt.Println("Error marshaling JSON(withdraw):", err) + return + } + var withdrawResponseData interface{} + err = json.Unmarshal(jsonBytes, &withdrawResponseData) + if err != nil { + fmt.Println("Error unmarshalling JSON(withdraw):", err) + return + } + + logInputAndOutput([]interface{}{addr.Address, 1000}, withdrawResponseData) + + fmt.Println("============================================") + fmt.Println("|| Done: All methods tested successfully! ||") + fmt.Println("============================================") } diff --git a/wrappers/fedimint-go/go.mod b/wrappers/fedimint-go/go.mod index 015fe7f..c50e3e5 100644 --- a/wrappers/fedimint-go/go.mod +++ b/wrappers/fedimint-go/go.mod @@ -2,8 +2,16 @@ module fedimint-go-client go 1.21.3 +require github.com/stretchr/testify v1.9.0 + +require github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 // indirect + require ( github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1 v1.0.4 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 github.com/joho/godotenv v1.5.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/wrappers/fedimint-go/go.sum b/wrappers/fedimint-go/go.sum index ca953b9..1fce7d4 100644 --- a/wrappers/fedimint-go/go.sum +++ b/wrappers/fedimint-go/go.sum @@ -1,6 +1,21 @@ github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1 v1.0.4 h1:0XErmfJBiVbl0NvyclGn4jr+1hIylDf5beFi9W0o7Fc= +github.com/decred/dcrd/dcrec/secp256k1 v1.0.4/go.mod h1:00z7mJdugt+GBAzPN1QrDRGCXxyKUiexEHu6ukxEw3k= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 h1:3GIJYXQDAKpLEFriGFN8SbSffak10UXHGdIcFaMPykY= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/wrappers/fedimint-go/pkg/fedimint/client.go b/wrappers/fedimint-go/pkg/fedimint/client.go index 9fc153a..a4ce78c 100644 --- a/wrappers/fedimint-go/pkg/fedimint/client.go +++ b/wrappers/fedimint-go/pkg/fedimint/client.go @@ -91,7 +91,7 @@ func (fc *FedimintClient) SetActiveGatewayId(gatewayId string) { func (fc *FedimintClient) UseDefaultGateway() error { // hits list_gateways and sets activeGatewayId to the first gateway - gateways, err := fc.Ln.ListGateways() + gateways, err := fc.Ln.ListGateways(nil) if err != nil { return fmt.Errorf("error getting gateways: %w", err) } @@ -107,82 +107,110 @@ func (fc *FedimintClient) get(endpoint string) ([]byte, error) { return fc.fetchWithAuth(endpoint, "GET", nil) } +// Post performs a POST request with JSON body, handling JSON marshalling within. func (fc *FedimintClient) post(endpoint string, body interface{}) ([]byte, error) { jsonBody, err := json.Marshal(body) if err != nil { - return nil, err + return nil, fmt.Errorf("error marshaling request body: %w", err) } - fmt.Println("jsonBody: ", string(jsonBody)) + + fmt.Printf("jsonBody: %s\n", jsonBody) + // Assuming fetchWithAuth is correctly implemented. return fc.fetchWithAuth(endpoint, "POST", jsonBody) } -func (fc *FedimintClient) postWithFederationId(endpoint string, body interface{}, federationId *string) ([]byte, error) { - // Marshal the original body to JSON - originalBodyJSON, err := json.Marshal(body) - if err != nil { - return nil, err - } +// postWithFederationId takes any request object, marshals it to JSON, optionally adds a federationId, and makes a POST request. +func (fc *FedimintClient) postWithFederationId(endpoint string, requestBody interface{}, federationId *string) ([]byte, error) { + // Initialize an empty map for the request body. + requestMap := make(map[string]interface{}) - // Unmarshal the JSON into a map to add federationId - var bodyMap map[string]interface{} - err = json.Unmarshal(originalBodyJSON, &bodyMap) - if err != nil { - return nil, err + // If the requestBody is not nil and not empty, marshal and unmarshal it into the map. + if requestBody != nil { + requestJSON, err := json.Marshal(requestBody) + if err != nil { + return nil, fmt.Errorf("failed to marshal request body: %w", err) + } + + // Unmarshal the JSON into the map only if it's not empty to avoid overwriting the initialized map. + if string(requestJSON) != "{}" { + err = json.Unmarshal(requestJSON, &requestMap) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal request JSON into map: %w", err) + } + } } - // Add federationId to the map + // Determine the effective federationId to use effectiveFederationId := fc.ActiveFederationId + fmt.Printf("effectiveFederationId: %s\n", effectiveFederationId) if federationId != nil { effectiveFederationId = *federationId } - bodyMap["federationId"] = effectiveFederationId + fmt.Printf("effectiveFederationId: %s\n", effectiveFederationId) + + // Add federationId to the map, which is now guaranteed to be initialized. + requestMap["federationId"] = effectiveFederationId - // Marshal the modified map back to JSON - modifiedBodyJSON, err := json.Marshal(bodyMap) + // Marshal the request map back to JSON to use as the request body. + modifiedRequestJSON, err := json.Marshal(requestMap) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to marshal modified request map: %w", err) } - // Use the modified JSON as the body for the POST request - return fc.fetchWithAuth(endpoint, "POST", modifiedBodyJSON) + fmt.Printf("modifiedRequestJSON: %s\n", modifiedRequestJSON) + + // Proceed to make the POST request with the modified JSON body. + return fc.fetchWithAuth(endpoint, "POST", modifiedRequestJSON) } -func (fc *FedimintClient) postWithGatewayIdAndFederationId(endpoint string, body interface{}, gatewayId *string, federationId *string) ([]byte, error) { - // Marshal the original body to JSON - originalBodyJSON, err := json.Marshal(body) - if err != nil { - return nil, err - } +func (fc *FedimintClient) postWithGatewayIdAndFederationId(endpoint string, requestBody interface{}, gatewayId *string, federationId *string) ([]byte, error) { + // Initialize an empty map for the request body. + requestMap := make(map[string]interface{}) - // Unmarshal the JSON into a map to add federationId - var bodyMap map[string]interface{} - err = json.Unmarshal(originalBodyJSON, &bodyMap) - if err != nil { - return nil, err + // If the requestBody is not nil and not empty, marshal and unmarshal it into the map. + if requestBody != nil { + requestJSON, err := json.Marshal(requestBody) + if err != nil { + return nil, fmt.Errorf("failed to marshal request body: %w", err) + } + + // Unmarshal the JSON into the map only if it's not empty to avoid overwriting the initialized map. + if string(requestJSON) != "{}" { + err = json.Unmarshal(requestJSON, &requestMap) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal request JSON into map: %w", err) + } + } } - // Add federationId to the map + // Determine the effective federationId to use effectiveFederationId := fc.ActiveFederationId if federationId != nil { effectiveFederationId = *federationId } - bodyMap["federationId"] = effectiveFederationId + fmt.Printf("effectiveFederationId: %s\n", effectiveFederationId) + requestMap["federationId"] = effectiveFederationId - // Add gatewayId to the map + // Determine the effective gatewayId to use effectiveGatewayId := fc.ActiveGatewayId if gatewayId != nil { effectiveGatewayId = *gatewayId } - bodyMap["gatewayId"] = effectiveGatewayId + fmt.Printf("effectiveGatewayId: %s\n", effectiveGatewayId) - // Marshal the modified map back to JSON - modifiedBodyJSON, err := json.Marshal(bodyMap) + // Add gatewayId to the map, which is now guaranteed to be initialized. + requestMap["gatewayId"] = effectiveGatewayId + + // Marshal the request map back to JSON to use as the request body. + modifiedRequestJSON, err := json.Marshal(requestMap) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to marshal modified request map: %w", err) } - // Use the modified JSON as the body for the POST request - return fc.fetchWithAuth(endpoint, "POST", modifiedBodyJSON) + fmt.Printf("modifiedRequestJSON: %s\n", modifiedRequestJSON) + + // Proceed to make the POST request with the modified JSON body. + return fc.fetchWithAuth(endpoint, "POST", modifiedRequestJSON) } func (fc *FedimintClient) Info() (*types.InfoResponse, error) { @@ -276,10 +304,6 @@ func (fc *FedimintClient) Join(inviteCode string, setActiveFederationId bool, us if setActiveFederationId { fc.SetActiveFederationId(response.ThisFederationId, useDefaultGateway) } - - if err != nil { - return response, err - } return response, nil } @@ -287,7 +311,7 @@ func (fc *FedimintClient) Join(inviteCode string, setActiveFederationId bool, us // Onchain // //////////// -func (onchain *OnchainModule) createDepositAddress(timeout int, federationId *string) (*modules.OnchainDepositAddressResponse, error) { +func (onchain *OnchainModule) CreateDepositAddress(timeout int, federationId *string) (*modules.OnchainDepositAddressResponse, error) { request := modules.OnchainDepositAddressRequest{Timeout: timeout} resp, err := onchain.Client.postWithFederationId("/onchain/deposit-address", request, federationId) if err != nil { @@ -301,7 +325,7 @@ func (onchain *OnchainModule) createDepositAddress(timeout int, federationId *st return &depositAddressResp, nil } -func (onchain *OnchainModule) awaitDeposit(operationId string, federationId *string) (*modules.OnchainAwaitDepositResponse, error) { +func (onchain *OnchainModule) AwaitDeposit(operationId string, federationId *string) (*modules.OnchainAwaitDepositResponse, error) { request := modules.OnchainAwaitDepositRequest{OperationId: operationId} resp, err := onchain.Client.postWithFederationId("/onchain/await-deposit", request, federationId) if err != nil { @@ -315,7 +339,7 @@ func (onchain *OnchainModule) awaitDeposit(operationId string, federationId *str return &depositResp, nil } -func (onchain *OnchainModule) withdraw(address string, amountSat int, federationId *string) (*modules.OnchainWithdrawResponse, error) { +func (onchain *OnchainModule) Withdraw(address string, amountSat int, federationId *string) (*modules.OnchainWithdrawResponse, error) { request := modules.OnchainWithdrawRequest{Address: address, AmountSat: amountSat} resp, err := onchain.Client.postWithFederationId("/onchain/withdraw", request, federationId) if err != nil { @@ -333,9 +357,9 @@ func (onchain *OnchainModule) withdraw(address string, amountSat int, federation // mint // ////////// -func (mint *MintModule) DecodeNotes(notes string, federationId *string) (*modules.DecodeNotesResponse, error) { +func (mint *MintModule) DecodeNotes(notes string) (*modules.DecodeNotesResponse, error) { request := modules.DecodeNotesRequest{Notes: notes} - resp, err := mint.Client.postWithFederationId("/mint/decode-notes", request, federationId) + resp, err := mint.Client.post("/mint/decode-notes", request) if err != nil { return nil, err } @@ -347,13 +371,13 @@ func (mint *MintModule) DecodeNotes(notes string, federationId *string) (*module return &decodeResp, nil } -func (mint *MintModule) EncodeNotes(notesJson modules.NotesJson, federationId *string) (*modules.EncodeNotesResponse, error) { +func (mint *MintModule) EncodeNotes(notesJson modules.NotesJson) (*modules.EncodeNotesResponse, error) { notesJsonStr, err := json.Marshal(notesJson) if err != nil { return nil, err } request := modules.EncodeNotesRequest{NotesJsonStr: string(notesJsonStr)} - resp, err := mint.Client.postWithFederationId("/mint/encode-notes", request, federationId) + resp, err := mint.Client.post("/mint/encode-notes", request) if err != nil { return nil, err } @@ -462,7 +486,7 @@ func (ln *LnModule) CreateInvoice(amountMsat uint64, description string, expiryT return &invoiceResp, nil } -func (ln *LnModule) CreateInvoiceForPubkey(pubkey string, amountMsat uint64, description string, expiryTime *int, gatewayId *string, federationId *string) (*modules.LnInvoiceResponse, error) { +func (ln *LnModule) CreateInvoiceForPubkey(pubkey string, amountMsat uint64, description string, gatewayId string, expiryTime *int, federationId *string) (*modules.LnInvoiceResponse, error) { request := modules.LnInvoiceExternalPubkeyRequest{ AmountMsat: amountMsat, Description: description, @@ -470,7 +494,7 @@ func (ln *LnModule) CreateInvoiceForPubkey(pubkey string, amountMsat uint64, des ExternalPubkey: pubkey, } fmt.Println("request: ", request) - resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/invoice-external-pubkey", request, gatewayId, federationId) + resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/invoice-external-pubkey", request, &gatewayId, federationId) if err != nil { return nil, err } @@ -482,7 +506,7 @@ func (ln *LnModule) CreateInvoiceForPubkey(pubkey string, amountMsat uint64, des return &invoiceResp, nil } -func (ln *LnModule) CreateInvoiceForPubkeyTweak(pubkey string, tweak uint64, amountMsat uint64, description string, expiryTime *int, gatewayId *string, federationId *string) (*modules.LnInvoiceResponse, error) { +func (ln *LnModule) CreateInvoiceForPubkeyTweak(pubkey string, tweak uint64, amountMsat uint64, description string, gatewayId string, expiryTime *int, federationId *string) (*modules.LnInvoiceResponse, error) { request := modules.LnInvoiceExternalPubkeyTweakedRequest{ AmountMsat: amountMsat, Description: description, @@ -491,7 +515,7 @@ func (ln *LnModule) CreateInvoiceForPubkeyTweak(pubkey string, tweak uint64, amo Tweak: tweak, } fmt.Println("request: ", request) - resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/invoice-external-pubkey-tweaked", request, gatewayId, federationId) + resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/invoice-external-pubkey-tweaked", request, &gatewayId, federationId) if err != nil { return nil, err } @@ -503,9 +527,9 @@ func (ln *LnModule) CreateInvoiceForPubkeyTweak(pubkey string, tweak uint64, amo return &invoiceResp, nil } -func (ln *LnModule) ClaimPubkeyReceive(privateKey string, federationId *string) (*types.InfoResponse, error) { +func (ln *LnModule) ClaimPubkeyReceive(privateKey string, gatewayId string, federationId *string) (*types.InfoResponse, error) { request := modules.LnClaimPubkeyReceiveRequest{PrivateKey: privateKey} - resp, err := ln.Client.postWithFederationId("/ln/claim-external-receive", request, federationId) + resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/claim-external-receive", request, &gatewayId, federationId) if err != nil { return nil, err } @@ -517,9 +541,9 @@ func (ln *LnModule) ClaimPubkeyReceive(privateKey string, federationId *string) return &infoResp, nil } -func (ln *LnModule) ClaimPubkeyReceiveTweaked(privateKey string, tweaks []uint64, federationId *string) (*types.InfoResponse, error) { +func (ln *LnModule) ClaimPubkeyTweakReceive(privateKey string, tweaks []uint64, gatewayId string, federationId string) (*types.InfoResponse, error) { request := modules.LnClaimPubkeyTweakedRequest{PrivateKey: privateKey, Tweaks: tweaks} - resp, err := ln.Client.postWithFederationId("/ln/claim-external-receive-tweaked", request, federationId) + resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/claim-external-receive-tweaked", request, &gatewayId, &federationId) if err != nil { return nil, err } @@ -531,9 +555,9 @@ func (ln *LnModule) ClaimPubkeyReceiveTweaked(privateKey string, tweaks []uint64 return &infoResp, nil } -func (ln *LnModule) AwaitInvoice(operationId string, federationId *string) (*types.InfoResponse, error) { +func (ln *LnModule) AwaitInvoice(operationId string, gatewayId string, federationId *string) (*types.InfoResponse, error) { request := modules.LnAwaitInvoiceRequest{OperationId: operationId} - resp, err := ln.Client.postWithFederationId("/ln/await-invoice", request, federationId) + resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/await-invoice", request, &gatewayId, federationId) if err != nil { return nil, err } @@ -545,17 +569,20 @@ func (ln *LnModule) AwaitInvoice(operationId string, federationId *string) (*typ return &infoResp, nil } -func (ln *LnModule) Pay(paymentInfo string, amountMsat *uint64, lnurlComment *string, gatewayId *string, federationId *string) (*modules.LnPayResponse, error) { +func (ln *LnModule) Pay(paymentInfo string, gatewayId string, amountMsat *uint64, lnurlComment *string, federationId *string) (*modules.LnPayResponse, error) { request := modules.LnPayRequest{ PaymentInfo: paymentInfo, AmountMsat: amountMsat, LnurlComment: lnurlComment, } fmt.Println("request: ", request) - resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/pay", request, gatewayId, federationId) + resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/pay", request, &gatewayId, federationId) if err != nil { return nil, err } + + fmt.Printf("Raw response body: %s\n", string(resp)) + var payResp modules.LnPayResponse err = json.Unmarshal(resp, &payResp) if err != nil { @@ -564,8 +591,8 @@ func (ln *LnModule) Pay(paymentInfo string, amountMsat *uint64, lnurlComment *st return &payResp, nil } -func (ln *LnModule) ListGateways() ([]modules.Gateway, error) { - resp, err := ln.Client.get("/ln/list-gateways") +func (ln *LnModule) ListGateways(federationId *string) ([]modules.Gateway, error) { + resp, err := ln.Client.postWithFederationId("/ln/list-gateways", nil, federationId) if err != nil { return nil, err } diff --git a/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go b/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go index 2f1466c..1ecebda 100644 --- a/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go +++ b/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go @@ -45,11 +45,16 @@ type LnPayRequest struct { LnurlComment *string `json:"lnurlComment"` } +type PaymentTypeInfo struct { + Internal *string `json:"internal,omitempty"` + Lightning *string `json:"lightning,omitempty"` +} + type LnPayResponse struct { - PperationId string `json:"operationId"` - PaymentType string `json:"paymentType"` - ContractId string `json:"contractId"` - Fee int `json:"fee"` + OperationId string `json:"operationId"` + PaymentType PaymentTypeInfo `json:"paymentType"` + ContractId string `json:"contractId"` + Fee int `json:"fee"` } type AwaitLnPayRequest struct { @@ -59,13 +64,13 @@ type AwaitLnPayRequest struct { type GatewayInfo struct { API string `json:"api"` Fees GatewayFees `json:"fees"` - GatewayID string `json:"gatewayId"` - GatewayRedeemKey string `json:"gatewayRedeemKey"` - LightningAlias string `json:"lightningAlias"` - MintChannelID int `json:"mintChannelId"` - NodePubKey string `json:"nodePubKey"` - RouteHints []interface{} `json:"routeHints"` // Adjust the type according to the actual structure of route hints - SupportsPrivatePayments bool `json:"supportsPrivatePayments"` + GatewayID string `json:"gateway_id"` + GatewayRedeemKey string `json:"gateway_redeem_key"` + LightningAlias string `json:"lightning_alias"` + MintChannelID int `json:"mint_channel_id"` + NodePubKey string `json:"node_pub_key"` + RouteHints []interface{} `json:"route_hints"` // Consider defining a more specific type if possible + SupportsPrivatePayments bool `json:"supports_private_payments"` } type GatewayFees struct { @@ -79,15 +84,10 @@ type GatewayTTL struct { } type Gateway struct { - FederationID string `json:"federationId"` + FederationID string `json:"federation_id"` Info GatewayInfo `json:"info"` TTL GatewayTTL `json:"ttl"` Vetted bool `json:"vetted"` } -// string::> FederationId type ListGatewaysResponse map[string][]Gateway - -type SwitchGatewayRequest struct { - GatewayId string `json:"gatewayId"` -} diff --git a/wrappers/fedimint-go/pkg/fedimint/types/modules/mint.go b/wrappers/fedimint-go/pkg/fedimint/types/modules/mint.go index 1b6c5a5..a743b6b 100644 --- a/wrappers/fedimint-go/pkg/fedimint/types/modules/mint.go +++ b/wrappers/fedimint-go/pkg/fedimint/types/modules/mint.go @@ -63,7 +63,7 @@ type DecodeNotesRequest struct { } type DecodeNotesResponse struct { - NotesJson string `json:"notesJson"` + NotesJson NotesJson `json:"notesJson"` } type EncodeNotesRequest struct { @@ -89,8 +89,8 @@ type MintSpendRequest struct { } type MintSpendResponse struct { - OperationId string `json:"operationId"` - Notes OOBNotes `json:"notes"` + OperationId string `json:"operationId"` + Notes string `json:"notes"` } type MintValidateRequest struct { diff --git a/wrappers/fedimint-py/AsyncFedimintClient.py b/wrappers/fedimint-py/AsyncFedimintClient.py index 95a26a8..bd08e22 100644 --- a/wrappers/fedimint-py/AsyncFedimintClient.py +++ b/wrappers/fedimint-py/AsyncFedimintClient.py @@ -380,7 +380,7 @@ def __init__(self, client): async def create_deposit_address(self, timeout: int, federation_id: str = None): request: OnchainDepositAddressRequest = {"timeout": timeout} return await self.client._post_with_federation_id( - "/wallet/deposit-address", request, federation_id + "/onchain/deposit-address", request, federation_id ) async def await_deposit( @@ -388,7 +388,7 @@ async def await_deposit( ) -> OnchainAwaitDepositResponse: request: OnchainAwaitDepositRequest = {"operationId": operation_id} return await self.client._post_with_federation_id( - "/wallet/await-deposit", request, federation_id + "/onchain/await-deposit", request, federation_id ) async def withdraw( @@ -402,5 +402,5 @@ async def withdraw( "amountSat": amount_sat, } return await self.client._post_with_federation_id( - "/wallet/withdraw", request, federationId + "/onchain/withdraw", request, federationId ) diff --git a/wrappers/fedimint-py/FedimintClient.py b/wrappers/fedimint-py/FedimintClient.py index ecd5810..07b4c57 100644 --- a/wrappers/fedimint-py/FedimintClient.py +++ b/wrappers/fedimint-py/FedimintClient.py @@ -70,6 +70,7 @@ def __init__( def get_active_federation_id(self): return self.active_federation_id + # *** def set_active_federation_id(self, federation_id: str): self.active_federation_id = federation_id @@ -162,9 +163,11 @@ def discover_version(self, threshold: int) -> DiscoverVersionResponse: def federation_ids(self): return self._get("/admin/federation-ids") + # *** def list_operations(self, request: ListOperationsRequest): return self._post_with_federation_id("/admin/list-operations", request) + # *** def join(self, invite_code: str, use_manual_secret: bool = False): return self._post( "/admin/join", @@ -342,7 +345,7 @@ def __init__(self, client): def create_deposit_address(self, timeout: int, federation_id: str = None): request: OnchainDepositAddressRequest = {"timeout": timeout} return self.client._post_with_federation_id( - "/wallet/deposit-address", request, federation_id + "/onchain/deposit-address", request, federation_id ) def await_deposit( @@ -350,7 +353,7 @@ def await_deposit( ) -> OnchainAwaitDepositResponse: request: OnchainAwaitDepositRequest = {"operationId": operation_id} return self.client._post_with_federation_id( - "/wallet/await-deposit", request, federation_id + "/onchain/await-deposit", request, federation_id ) def withdraw( @@ -364,5 +367,5 @@ def withdraw( "amountSat": amount_sat, } return self.client._post_with_federation_id( - "/wallet/withdraw", request, federation_id + "/onchain/withdraw", request, federation_id ) diff --git a/wrappers/fedimint-ts/FedimintClient.ts b/wrappers/fedimint-ts/FedimintClient.ts index da35cd3..fda8926 100644 --- a/wrappers/fedimint-ts/FedimintClient.ts +++ b/wrappers/fedimint-ts/FedimintClient.ts @@ -289,7 +289,6 @@ class FedimintClient { gatewayId: effectiveGatewayId, }); } catch (error) { - console.error("Error posting with federation and gateway id: ", error); throw error; } } @@ -559,7 +558,6 @@ class FedimintClient { const request: MintEncodeNotesRequest = { notesJsonStr: JSON.stringify(notesJson), }; - console.log("request: ", request); return await this.post( "/mint/encode-notes", @@ -677,7 +675,7 @@ class FedimintClient { const request: OnchainDepositAddressRequest = { timeout }; return await this.postWithFederationId( - "/wallet/deposit-address", + "/onchain/deposit-address", request, federationId ); @@ -696,7 +694,7 @@ class FedimintClient { const request: OnchainAwaitDepositRequest = { operationId }; return await this.postWithFederationId( - "/wallet/await-deposit", + "/onchain/await-deposit", request, federationId ); @@ -720,7 +718,7 @@ class FedimintClient { const request: OnchainWithdrawRequest = { address, amountSat }; return await this.postWithFederationId( - "/wallet/withdraw", + "/onchain/withdraw", request, federationId );