Skip to content

Commit

Permalink
Implement SEP0010 transaction challenge builder.
Browse files Browse the repository at this point in the history
  • Loading branch information
abuiles committed Jul 19, 2019
1 parent fe128f8 commit 82d7d28
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Expand Up @@ -27,6 +27,7 @@ export {
SERVER_TIME_MAP,
getCurrentServerTime,
} from "./horizon_axios_client";
export * from "./utils";

// expose classes and functions from stellar-base
export * from "stellar-base";
Expand Down
51 changes: 51 additions & 0 deletions src/utils.ts
@@ -0,0 +1,51 @@
import { randomBytes } from "crypto";
import { Account, Keypair, Operation, TransactionBuilder } from "stellar-base";

/**
* Collection on util functions
*
* @namespace Utils
*/
export namespace Utils {
/**
* Returns a valid SEP0010 challenge which you can use for Stellar Web Authentication.
*
* @see [SEP0010: Stellar Web Authentication](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md)
* @param {Keypair} serverKeypair Server's keypair.
* @param {string} clientAccountID Client's Stellar account.
* @param {string} anchorName.
* @param {number} [timeout=300] Challenge duration (default to 5 minutes).
*/
export function buildChallengeTx(
serverKeypair: Keypair,
clientAccountID: string,
anchorName: string,
timeout: number = 300,
): string {
const account = new Account(serverKeypair.publicKey(), "-1");
const now = Math.floor(Date.now() / 1000);

const transaction = new TransactionBuilder(account, {
fee: 100,
timebounds: {
minTime: now,
maxTime: now + timeout,
},
})
.addOperation(
Operation.manageData({
name: `${anchorName} auth`,
value: randomBytes(64),
source: clientAccountID,
}),
)
.build();

transaction.sign(serverKeypair);

return transaction
.toEnvelope()
.toXDR("base64")
.toString();
}
}
45 changes: 45 additions & 0 deletions test/unit/utils_test.js
@@ -0,0 +1,45 @@
describe('Utils', function() {
describe('Utils.buildChallengeTx', function() {
it('returns challenge which follows SEP0010 spec', function() {
let keypair = StellarSdk.Keypair.random();

const challenge = StellarSdk.Utils.buildChallengeTx(
keypair,
"GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF",
"SDF"
);

const transaction = new StellarSdk.Transaction(challenge);

expect(transaction.sequence).to.eql("0");
expect(transaction.source).to.eql(keypair.publicKey());
expect(transaction.operations.length).to.eql(1);

const { maxTime, minTime } = transaction.timeBounds;

expect(parseInt(maxTime) - parseInt(minTime)).to.eql(300);

const [ operation ] = transaction.operations;

expect(operation.name).to.eql("SDF auth");
expect(operation.source).to.eql("GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF");
expect(operation.type).to.eql("manageData");
expect(operation.value.length).to.eql(64);
});

it('uses the passed-in timeout', function() {
let keypair = StellarSdk.Keypair.random();

const challenge = StellarSdk.Utils.buildChallengeTx(
keypair,
"GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF",
"SDF",
600
);

const transaction = new StellarSdk.Transaction(challenge);
const { maxTime, minTime } = transaction.timeBounds;
expect(parseInt(maxTime) - parseInt(minTime)).to.eql(600);
});
});
});

0 comments on commit 82d7d28

Please sign in to comment.