Skip to content

Commit

Permalink
SignRequest parse -> Pact Command Payload -> Sign, Quicksign sign ind…
Browse files Browse the repository at this point in the history
…ividual CommandSigData
  • Loading branch information
Sterling Long committed Mar 10, 2023
1 parent ae13155 commit bc89c4d
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 106 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2.0.0

- Changes to sign function in the SigningApi class so you can parse -> Pact Command Payload -> Sign
- Added function to sign individual CommandSigData from a QuicksignRequest so wallets can display each and sign each individually
- Bug fixes and test updates

## 1.0.1

- Updated readme to give correct quickstart guide
Expand Down
144 changes: 129 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,58 @@ This is an SDK in dart for interacting with the Kadena blockchain.

## Sign and Quicksign Usage

### dApp Usage

```dart
import 'package:kadena_dart_sdk/kadena_dart_sdk.dart';
// Create a signing API object
ISigningApi signingApi = SigningApi();
// Create a sign or quicksign request
SignRequest signRequest = SignRequest(
code: '"Hello"',
data: {},
sender: 'sender',
networkId: 'testnet04',
chainId: '1',
gasLimit: 1000,
gasPrice: 1e-5,
signingPubKey: 'pubKey',
ttl: 600,
caps: [
DappCapp(
role: 'Gas',
description: 'Gas Cap',
cap: Capability(
name: 'Gas',
args: [
],
),
),
],
);
QuicksignRequest quicksignRequest = QuicksignRequest(
commandSigDatas: [
CommandSigData(
cmd: 'Hello, World!', // This is not a valid stringified Pact Command Payload, be warned
sigs: [
QuicksignSigner(
pubKey: 'pubKey',
),
],
),
],
);
// You can send the object across a pipe by transforming it into json
final signRequestJson = signRequest.toJson();
final quicksignRequestJson = quicksignRequest.toJson();
```

### Wallet Usage

```dart
import 'package:kadena_dart_sdk/kadena_dart_sdk.dart';
Expand All @@ -16,7 +68,7 @@ final KadenaSignKeyPair kp = KadenaSignKeyPair(
privateKey: 'pub_key',
);
// Take the Sign/Quicksign Request object as a JSON map
// Take the Sign/Quicksign Request object received from the dApp
final Map<String, dynamic> quicksignRequestJson = {
"commandSigDatas": [
{
Expand All @@ -32,41 +84,103 @@ final Map<String, dynamic> quicksignRequestJson = {
};
final Map<String, dynamic> signRequestJson = {
"code": '"Hello"',
"data": {},
"sender": "sender",
"networkId": "testnet04",
"chainId": "1",
"gasLimit": 1000,
"gasPrice": 1e-5,
"signingPubKey": '8d48094ca84b475ece568c4b0d8aacfb1de3278b6bd16b33a60c068b86a2ba51',
"ttl": 600,
"caps": [
{
"role": "Gas",
"description": "Gas Cap",
"cap": {
"name": "Gas",
"args": []
}
}
]
};
// Parse the requests
final QuicksignRequest quicksignRequest = signingApi.parseQuicksignRequest(
quicksignRequestJson,
);
/// Sign Request Flow ///
// 1. Parse the request
final SignRequest signRequest = signingApi.parseSignRequest(
signRequestJson,
);
// Feed the quicksign function with the keypair and quicksign request
final QuicksignResult quicksignResult = signingApi.quicksign(
request: quicksignRequest,
keyPairs: [kp],
);
final SignResult signResult = signingApi.quicksign(
// 2. Construct a PactCommandPayload with it
final PactCommandPayload pactCommandPayload = signingApi.constructPactCommandPayload(
request: signRequest,
keyPairs: kp,
);
// If you need to send the QuicksignResult across HTTP or Websocket (Like Wallet Connect)
// you can turn it into JSON
final Map<String, dynamic> quicksignResultJson = quicksignResult.toJson();
// 3. Get user's approval to sign the transaction in some way (Alert, Popup, Bottom Sheet etc.)
final bool approval = true;
// 4. Sign the transaction
SignResult signResult
if (approval) {
signResult = signingApi.sign(
request: signRequest,
keyPairs: kp,
);
}
else {
signResult = SignResult(
error: SignRequestError(
msg: 'User declined to sign',
),
);
}
// 5. Return the sign result to the dApp in JSON format
final Map<String, dynamic> signResultJson = signResult.toJson();
/// Quicksign Flow ///
// 1. Parse the requests
final QuicksignRequest quicksignRequest = signingApi.parseQuicksignRequest(
quicksignRequestJson,
);
// 2. Store the QuicksignResponses, and loop through each CommandSigData in the QuicksignRequest
final List<QuicksignResponse> quicksignResponseList = [];
for (final CommandSigData commandSigData in quicksignRequest.commandSigDatas) {
// 3. Get the uer's approval to sign the transaction in some way (Alert, Popup, Bottom Sheet etc.)
var approval = true;
// 4. Depending on the approval, sign the transaction or add a noSig QuicksignOutcome
if (approval) {
final QuicksignResult quicksignResult = signingApi.quicksignSingleCommand(
commandSigData: commandSigData,
keyPairs: kp,
);
quicksignResponseList.add(quicksignResult);
}
else {
quicksignResponseList.add(
QuicksignResponse(
commandSigData: commandSigData
outcome: QuicksignOutcome(
result: QuicksignOutcome.noSig,
),
),
);
}
}
// 5. Return a QuicksignResult to the dApp in JSON format
final QuicksignResult quicksignResult = QuicksignResult(
responses: quicksignResponseList,
).toJson();
```

## Implementation

The ISigningApi is an interface so that you can mock it easily, and so that it is possible to create future versions that can easily be replaced with the current implementation.

This library is meant to make it easy for dApps to build requests and for wallets to sign them.

## Tests

To run the tests:
Expand Down
19 changes: 16 additions & 3 deletions lib/signing_api/i_signing_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,35 @@ abstract class ISigningApi {
required Map<String, dynamic> request,
});

/// Takes the SignRequest object, and constructs a Pact Command Payload with it
PactCommandPayload constructPactCommandPayload({
required SignRequest request,
});

/// Takes the SigningRequest object, constructs a Pact Payload with it
/// and signs it with the keyPair.
SignResult sign({
required PactCommandPayload payload,
required KadenaSignKeyPair keyPair,
required SignRequest request,
});

/// Attempts to parse the JSON map "request" into a SigningRequest object.
/// Throws errors on failure.
/// See https://github.com/kadena-io/KIPs/blob/jam/quicksign/kip-0015.md for the Quicksign spec.
/// See https://github.com/kadena-io/KIPs/blob/master/kip-0015.md for the Quicksign spec.
QuicksignRequest parseQuicksignRequest({
required Map<String, dynamic> request,
});

/// Takes a commandSigData and signs it with the keyPair.
/// See https://github.com/kadena-io/KIPs/blob/master/kip-0015.md for the CommandSigData spec,
/// and how you are meant to sign it, and respond to errors while signing.
QuicksignResponse quicksignSingleCommand({
required List<KadenaSignKeyPair> keyPairs,
required CommandSigData commandSigData,
});

/// Takes the QuicksignRequest object and signs each cmd in the request.
/// See https://github.com/kadena-io/KIPs/blob/jam/quicksign/kip-0015.md for the Quicksign spec.
/// See https://github.com/kadena-io/KIPs/blob/master/kip-0015.md for the Quicksign spec.
/// This accepts multiple key pairs because the signing wallet might contain multiple keys.
QuicksignResult quicksign({
required List<KadenaSignKeyPair> keyPairs,
Expand Down
Loading

0 comments on commit bc89c4d

Please sign in to comment.