SignPsbt
SignPsbt expects a partial transaction with all inputs and outputs fully declared and tries to sign all unsigned inputs that have all required fields (UTXO information, BIP32 derivation information, witness or sig scripts) set. If no error is returned, the PSBT is ready to be given to the next signer or to be finalized if lnd was the last signer.
NOTE: This RPC only signs inputs (and only those it can sign), it does not perform any other tasks (such as coin selection, UTXO locking or input/output/fee value validation, PSBT finalization). Any input that is incomplete will be skipped.
Source: walletrpc/walletkit.proto
gRPC
rpc SignPsbt (SignPsbtRequest) returns (SignPsbtResponse);
REST
| HTTP Method | Path |
|---|---|
| POST | /v2/wallet/psbt/sign |
Code Samples
- gRPC
- REST
- lncli
- Javascript
- Python
- grpcurl
const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const GRPC_HOST = 'localhost:10009'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
const TLS_PATH = 'LND_DIR/tls.cert'
const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync(['lightning.proto', 'walletrpc/walletkit.proto'], loaderOptions);
const walletrpc = grpc.loadPackageDefinition(packageDefinition).walletrpc;
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
const tlsCert = fs.readFileSync(TLS_PATH);
const sslCreds = grpc.credentials.createSsl(tlsCert);
const macaroon = fs.readFileSync(MACAROON_PATH).toString('hex');
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
let metadata = new grpc.Metadata();
metadata.add('macaroon', macaroon);
callback(null, metadata);
});
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
let client = new walletrpc.WalletKit(GRPC_HOST, creds);
let request = {
funded_psbt: <bytes>,
};
client.signPsbt(request, function(err, response) {
console.log(response);
});
// Console output:
// {
// "signed_psbt": <bytes>,
// "signed_inputs": <uint32>,
// }
import codecs, grpc, os
# Generate the following 2 modules by compiling the walletrpc/walletkit.proto with the grpcio-tools.
# See https://github.com/lightningnetwork/lnd/blob/master/docs/grpc/python.md for instructions.
import walletkit_pb2 as walletrpc, walletkit_pb2_grpc as walletkitstub
GRPC_HOST = 'localhost:10009'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
# create macaroon credentials
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
def metadata_callback(context, callback):
callback([('macaroon', macaroon)], None)
auth_creds = grpc.metadata_call_credentials(metadata_callback)
# create SSL credentials
os.environ['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA'
cert = open(TLS_PATH, 'rb').read()
ssl_creds = grpc.ssl_channel_credentials(cert)
# combine macaroon and SSL credentials
combined_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds)
# make the request
channel = grpc.secure_channel(GRPC_HOST, combined_creds)
stub = walletkitstub.WalletKitStub(channel)
request = walletrpc.SignPsbtRequest(
funded_psbt=<bytes>,
)
response = stub.SignPsbt(request)
print(response)
# {
# "signed_psbt": <bytes>,
# "signed_inputs": <uint32>,
# }
# grpcurl docs: https://github.com/fullstorydev/grpcurl
# Proto source: https://github.com/lightningnetwork/lnd
GRPC_HOST=localhost:10009
LND_DIR=~/.lnd
LND_SOURCE=path/to/lnd
NETWORK=mainnet
MACAROON_PATH="$LND_DIR/data/chain/bitcoin/$NETWORK/admin.macaroon"
TLS_PATH="$LND_DIR/tls.cert"
grpcurl \
-import-path $LND_SOURCE/lnrpc/ \
-proto walletrpc/walletkit.proto \
-cacert $TLS_PATH \
-H "macaroon: $(xxd -ps -u -c 1000 $MACAROON_PATH)" \
-d '{ "funded_psbt": BASE64_ENCODED_VALUE }' \
$GRPC_HOST \
walletrpc.WalletKit/SignPsbt
- Javascript
- Python
- curl
const fs = require('fs');
const request = require('request');
const REST_HOST = 'localhost:8080'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
let requestBody = {
funded_psbt: <string>, // <bytes> (base64 encoded)
};
let options = {
url: `https://${REST_HOST}/v2/wallet/psbt/sign`,
// Work-around for self-signed certificates.
rejectUnauthorized: false,
json: true,
headers: {
'Grpc-Metadata-macaroon': fs.readFileSync(MACAROON_PATH).toString('hex'),
},
form: JSON.stringify(requestBody),
}
request.post(options, function(error, response, body) {
console.log(body);
});
// Console output:
// {
// "signed_psbt": <string>, // <bytes>
// "signed_inputs": <array>, // <uint32>
// }
import base64, codecs, json, requests
REST_HOST = 'localhost:8080'
MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
TLS_PATH = 'LND_DIR/tls.cert'
url = f'https://{REST_HOST}/v2/wallet/psbt/sign'
macaroon = codecs.encode(open(MACAROON_PATH, 'rb').read(), 'hex')
headers = {'Grpc-Metadata-macaroon': macaroon}
data = {
'funded_psbt': base64.b64encode(<bytes>),
}
r = requests.post(url, headers=headers, data=json.dumps(data), verify=TLS_PATH)
print(r.json())
# {
# "signed_psbt": <bytes>,
# "signed_inputs": <uint32>,
# }
REST_HOST=localhost:8080
LND_DIR=~/.lnd
NETWORK=mainnet
MACAROON_PATH="$LND_DIR/data/chain/bitcoin/$NETWORK/admin.macaroon"
TLS_PATH="$LND_DIR/tls.cert"
curl -X POST \
--cacert $TLS_PATH \
-H "Grpc-Metadata-macaroon: $(xxd -ps -u -c 1000 $MACAROON_PATH)" \
-d '{ "funded_psbt": BASE64_ENCODED_VALUE }' \
https://$REST_HOST/v2/wallet/psbt/sign
$ lncli wallet psbt sign --help
NAME:
lncli wallet psbt sign - Sign a Partially Signed Bitcoin Transaction (PSBT).
USAGE:
lncli wallet psbt sign [command options] funded_psbt
DESCRIPTION:
The sign command expects a partial transaction with all inputs
and outputs fully declared and tries to sign all inputs that can be
identified by the wallet as belonging to it. All fields to identify a
signer, such as root key fingerprints, derivation paths and public keys,
must be set to be able to sign the transaction.
This method does NOT finalize or publish the transaction after it's been
signed. If lnd was the last signer and all required signatures are
present, use the finalize command to finalize the transaction.
OPTIONS:
--funded_psbt value the base64 encoded PSBT to sign
Messages
walletrpc.SignPsbtRequest
Source: walletrpc/walletkit.proto
| Field | gRPC Type | REST Type | REST Placement |
|---|---|---|---|
funded_psbt | bytes | string | body |
walletrpc.SignPsbtResponse
Source: walletrpc/walletkit.proto
| Field | gRPC Type | REST Type |
|---|---|---|
signed_psbt | bytes | string |
signed_inputs | uint32[] | array |