Can i get Python gRPC Sample for Transferring Balances from a Validator Party?

Hi everyone,

I am looking for a Python gRPC sample code to transfer balances from a validator party.

Current Progress:

  • I have successfully implemented party creation using gRPC.

  • The newly created parties are now visible and active on the network.

My Goal:
I am now trying to implement the balance transfer logic. Initially, I was exploring whether I could simply adjust the parameters of a CreateCommand and wrap it within a PrepareSubmissionRequest.

However, I suspect that I should be using an ExerciseCommand instead of a CreateCommand to trigger the transfer logic on an existing contract. I am having difficulty finding clear examples of how to properly structure the choiceArguments for this purpose.

Specific Questions:

  1. Is the ExerciseCommand within a PrepareSubmissionRequest the correct approach for transferring balances?

  2. How should the choiceArguments be formatted in Python when calling the transfer choice?

  3. Are there any gRPC sample snippets for Python that demonstrate this specific workflow (PrepareSubmission → Exercise)?

Any advice or code references would be a huge help. Thank you in advance!

Hi, @erdehoon! Welcome to the Daml Forums.

  1. Yes, transferring a CIP-56 asset requires exercising the TransferFactory_Transfer choice.

  2. Below, I am inserting a PrepareSubmissionRequest which works for me using Postman against LocalNet. It’s not Python code, but it does show the required fields and how they are Daml-LF encoded. (This was using the 0.5.5 Splice.)

  3. I am not aware of a Python implementation. There is the Wallet SDK in TypeScript and a Java sample, but they both use the JSON Ledger API, not the gPRC.

Does this get you unstuck?

PrepareSubmissionRequest gRPC sample
{
  "act_as": [
    "{{appProviderParty}}"
  ],
  "command_id": "command01",
  "commands": [
    {
      "exercise": {
        "template_id": {
          "package_id": "#splice-api-token-transfer-instruction-v1",
          "module_name": "Splice.Api.Token.TransferInstructionV1",
          "entity_name": "TransferFactory"
        },
        "contract_id": "{{factoryId}}",
        "choice": "TransferFactory_Transfer",
        "choice_argument": {
          "record": {
            "fields": [
              {
                "label": "expectedAdmin",
                "value": {
                  "party": "{{amuletAdminParty}}"
                }
              },
              {
                "label": "transfer",
                "value": {
                  "record": {
                    "fields": [
                      {
                        "label": "sender",
                        "value": {
                          "party": "{{appProviderParty}}"
                        }
                      },
                      {
                        "label": "receiver",
                        "value": {
                          "party": "{{appProviderParty}}"
                        }
                      },
                      {
                        "label": "amount",
                        "value": {
                          "numeric": "100"
                        }
                      },
                      {
                        "label": "instrumentId",
                        "value": {
                          "record": {
                            "fields": [
                              {
                                "label": "admin",
                                "value": {
                                  "party": "{{amuletAdminParty}}"
                                }
                              },
                              {
                                "label": "id",
                                "value": {
                                  "text": "Amulet"
                                }
                              }
                            ]
                          }
                        }
                      },
                      {
                        "label": "requestedAt",
                        "value": {
                          "timestamp": 1769705921000000
                        }
                      },
                      {
                        "label": "executeBefore",
                        "value": {
                          "timestamp": 1769755921000000
                        }
                      },
                      {
                        "label": "inputHoldingCids",
                        "value": {
                          "list": {
                            "elements": [
                              {
                                "contract_id": "{{assetContractId}}"
                              }
                            ]
                          }
                        }
                      },
                      {
                        "label": "meta",
                        "value": {
                          "record": {
                            "fields": [
                              {
                                "label": "values",
                                "value": {
                                  "text_map": {
                                    "entries": []
                                  }
                                }
                              }
                            ]
                          }
                        }
                      }
                    ]
                  }
                }
              },
              {
                "label": "extraArgs",
                "value": {
                  "record": {
                    "fields": [
                      {
                        "label": "context",
                        "value": {
                          "record": {
                            "fields": [
                              {
                                "label": "values",
                                "value": {
                                  "text_map": {
                                    "entries": [
                                      {
                                        "key": "open-round",
                                        "value": {
                                          "variant": {
                                            "constructor": "AV_ContractId",
                                            "value": {
                                              "contract_id": "{{openRoundContractId}}"
                                            }
                                          }
                                        }
                                      },
                                      {
                                        "key": "amulet-rules",
                                        "value": {
                                          "variant": {
                                            "constructor": "AV_ContractId",
                                            "value": {
                                              "contract_id": "{{amuletRulesContractId}}"
                                            }
                                          }
                                        }
                                      }
                                    ]
                                  }
                                }
                              }
                            ]
                          }
                        }
                      },
                      {
                        "label": "meta",
                        "value": {
                          "record": {
                            "fields": [
                              {
                                "label": "values",
                                "value": {
                                  "text_map": {
                                    "entries": []
                                  }
                                }
                              }
                            ]
                          }
                        }
                      }
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    }
  ],
  "disclosed_contracts": [
    {
      "template_id": {
        "package_id": "3ca1343ab26b453d38c8adb70dca5f1ead8440c42b59b68f070786955cbf9ec1",
        "module_name": "Splice.AmuletRules",
        "entity_name": "AmuletRules"
      },
      "contract_id": "{{amuletRulesContractId}}",
      "created_event_blob": "{{amuletRulesBlob}}",
      "synchronizer_id": "{{synchronizerId}}"
    },
    {
      "template_id": {
        "package_id": "3ca1343ab26b453d38c8adb70dca5f1ead8440c42b59b68f070786955cbf9ec1",
        "module_name": "Splice.Round",
        "entity_name": "OpenMiningRound"
      },
      "contract_id": "{{openMiningRoundContractId}}",
      "created_event_blob": "{{openMiningRoundBlob}}",
      "synchronizer_id": "{{synchronizerId}}"
    },
    {
      "template_id": {
        "package_id": "3ca1343ab26b453d38c8adb70dca5f1ead8440c42b59b68f070786955cbf9ec1",
        "module_name": "Splice.ExternalPartyAmuletRules",
        "entity_name": "ExternalPartyAmuletRules"
      },
      "contract_id": "{{externalPartyAmuletRulesContractId}}",
      "created_event_blob": "{{externalPartyAmuletRulesBlob}}",
      "synchronizer_id": "{{synchronizerId}}"
    }
  ],
  "estimate_traffic_cost": {
    "disabled": true
  }
}

Some of the content for the PrepareSubmissionRequest comes from Transfer Instruction HTTP endpoint. Here is an example of that:

TransferFactory sample request
{
  "choiceArguments": {
    "expectedAdmin": "DSO::1220676482a94a15dd1330f5fc8838e8cafdf63c2ba51f96dca3ad0bdc91970a543e",
    "transfer": {
      "sender": "{{appProviderParty}}",
      "receiver": "{{appProviderParty}}",
      "amount": 100,
      "instrumentId": {
        "admin": "{{amuletAdminParty}}",
        "id": "Amulet"
      },
      "requestedAt": "2026-01-29T12:00:00Z",
      "executeBefore": "2026-01-30T12:00:00Z",
      "inputHoldingCids": [
        "{{assetContractId}}"
      ],
      "meta": {
        "values": {}
      }
    },
    "extraArgs": {
        "meta": {
          "values": {}
        },
        "context": {
          "values": {}
        }
      }
    },
  "excludeDebugFields": true
}
TransferFactory sample response
{
    "factoryId": "00c99dc56948893a8ecfd1df10eba8a02e64cede2afeba5ab6df7f81dd847fc509ca1212202b39d63758e71a1727fc1b1a9690d59fb46c5f2f28a191a1deec982b6cb6216a",
    "transferKind": "self",
    "choiceContext": {
        "choiceContextData": {
            "values": {
                "open-round": {
                    "tag": "AV_ContractId",
                    "value": "00d2a760f569363c2f93b53399a8c86731e6a1a9dae15a458002d353d2683968e0ca121220431e19304d1310b42713c8801218aa36750ad75eca627dfabb1764035530d255"
                },
                "amulet-rules": {
                    "tag": "AV_ContractId",
                    "value": "007c3bc53e3cf7559eb6fecaa8a08dffdab7cd4e473f92e4b32b93f3d960d47393ca121220c1911e933952c5c40561d1a056ca7c6383f10b0d4e1d539f21421b8e6341864d"
                }
            }
        },
        "disclosedContracts": [
            {
                "templateId": "3ca1343ab26b453d38c8adb70dca5f1ead8440c42b59b68f070786955cbf9ec1:Splice.AmuletRules:AmuletRules",
                "contractId": "007c3bc53e3cf7559eb6fecaa8a08dffdab7cd4e473f92e4b32b93f3d960d47393ca121220c1911e933952c5c40561d1a056ca7c6383f10b0d4e1d539f21421b8e6341864d",
                "createdEventBlob": "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",
                "synchronizerId": "global-domain::1220676482a94a15dd1330f5fc8838e8cafdf63c2ba51f96dca3ad0bdc91970a543e",
                "debugPackageName": null,
                "debugPayload": null,
                "debugCreatedAt": null
            },
            {
                "templateId": "3ca1343ab26b453d38c8adb70dca5f1ead8440c42b59b68f070786955cbf9ec1:Splice.Round:OpenMiningRound",
                "contractId": "00d2a760f569363c2f93b53399a8c86731e6a1a9dae15a458002d353d2683968e0ca121220431e19304d1310b42713c8801218aa36750ad75eca627dfabb1764035530d255",
                "createdEventBlob": "CgMyLjESnAcKRQDSp2D1aTY8L5O1M5moyGcx5qGp2uFaRYAC01PSaDlo4MoSEiBDHhkwTRMQtCcTyIASGKo2dQrXXspiffq7F2QDVTDSVRINc3BsaWNlLWFtdWxldBpiCkAzY2ExMzQzYWIyNmI0NTNkMzhjOGFkYjcwZGNhNWYxZWFkODQ0MGM0MmI1OWI2OGYwNzA3ODY5NTVjYmY5ZWMxEgZTcGxpY2USBVJvdW5kGg9PcGVuTWluaW5nUm91bmQi3wRq3AQKTQpLOklEU086OjEyMjA2NzY0ODJhOTRhMTVkZDEzMzBmNWZjODgzOGU4Y2FmZGY2M2MyYmE1MWY5NmRjYTNhZDBiZGM5MTk3MGE1NDNlCgoKCGoGCgQKAhgqChAKDjIMMC4wMDUwMDAwMDAwCgsKCSnaRFSXikkGAAoLCgkp2tDa3opJBgAKDgoMagoKCAoGGID4pfBdCpsCCpgCapUCChYKFGoSChAKDjIMMC4wMDAwMDAwMDAwChYKFGoSChAKDjIMMC4wMDAwMTkwMjU5CqQBCqEBap4BChAKDjIMMC4wMDAwMDAwMDAwCokBCoYBWoMBCihqJgoSChAyDjEwMC4wMDAwMDAwMDAwChAKDjIMMC4wMDAwMDAwMDAwCilqJwoTChEyDzEwMDAuMDAwMDAwMDAwMAoQCg4yDDAuMDAwMDAwMDAwMAosaioKFgoUMhIxMDAwMDAwLjAwMDAwMDAwMDAKEAoOMgwwLjAwMDAwMDAwMDAKFgoUahIKEAoOMgwwLjAwMDAwMDAwMDAKEAoOMgwxLjAwMDAwMDAwMDAKBQoDGMgBCgUKAxjIAQoECgIYZAqUAQqRAWqOAQoaChgyFjQwMDAwMDAwMDAwLjAwMDAwMDAwMDAKEAoOMgwwLjA1MDAwMDAwMDAKEAoOMgwwLjE1MDAwMDAwMDAKEAoOMgwwLjIwMDAwMDAwMDAKEgoQMg4xMDAuMDAwMDAwMDAwMAoQCg4yDDAuNjAwMDAwMDAwMAoUChJSEAoOMgwyLjg1MDAwMDAwMDAKDgoMagoKCAoGGICYmrwEKklEU086OjEyMjA2NzY0ODJhOTRhMTVkZDEzMzBmNWZjODgzOGU4Y2FmZGY2M2MyYmE1MWY5NmRjYTNhZDBiZGM5MTk3MGE1NDNlOdr+kHOKSQYAQioKJgokCAESIJ5LLtghXEnTCdKes5C8nUQmkLgPMIFVtH2y3vj8z/oTEB4=",
                "synchronizerId": "global-domain::1220676482a94a15dd1330f5fc8838e8cafdf63c2ba51f96dca3ad0bdc91970a543e",
                "debugPackageName": null,
                "debugPayload": null,
                "debugCreatedAt": null
            },
            {
                "templateId": "3ca1343ab26b453d38c8adb70dca5f1ead8440c42b59b68f070786955cbf9ec1:Splice.ExternalPartyAmuletRules:ExternalPartyAmuletRules",
                "contractId": "00c99dc56948893a8ecfd1df10eba8a02e64cede2afeba5ab6df7f81dd847fc509ca1212202b39d63758e71a1727fc1b1a9690d59fb46c5f2f28a191a1deec982b6cb6216a",
                "createdEventBlob": "CgMyLjESqQMKRQDJncVpSIk6js/R3xDrqKAuZM7eKv66Wrbff4HdhH/FCcoSEiArOdY3WOcaFyf8GxqWkNWftGxfLyihkaHe7JgrbLYhahINc3BsaWNlLWFtdWxldBp+CkAzY2ExMzQzYWIyNmI0NTNkMzhjOGFkYjcwZGNhNWYxZWFkODQ0MGM0MmI1OWI2OGYwNzA3ODY5NTVjYmY5ZWMxEgZTcGxpY2USGEV4dGVybmFsUGFydHlBbXVsZXRSdWxlcxoYRXh0ZXJuYWxQYXJ0eUFtdWxldFJ1bGVzIlFqTwpNCks6SURTTzo6MTIyMDY3NjQ4MmE5NGExNWRkMTMzMGY1ZmM4ODM4ZThjYWZkZjYzYzJiYTUxZjk2ZGNhM2FkMGJkYzkxOTcwYTU0M2UqSURTTzo6MTIyMDY3NjQ4MmE5NGExNWRkMTMzMGY1ZmM4ODM4ZThjYWZkZjYzYzJiYTUxZjk2ZGNhM2FkMGJkYzkxOTcwYTU0M2U5ES7vsYdJBgBCKgomCiQIARIg/F6x2ZJUo0bkADClOVVrFe4VJXobfVZOURTV5X/7DNwQHg==",
                "synchronizerId": "global-domain::1220676482a94a15dd1330f5fc8838e8cafdf63c2ba51f96dca3ad0bdc91970a543e",
                "debugPackageName": null,
                "debugPayload": null,
                "debugCreatedAt": null
            }
        ]
    }
}

Hey @erdehoon,

It sounds like you’ve done a lot of work already but if you’re developing in Python we have an external signing example in python here if you haven’t seen it already. That doesn’t use the Wallet SDK but that’s only in TypeScript anyway.

1 Like