This repository has been archived by the owner on Nov 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
700 additions
and
188 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@onflow/flow-js-testing": minor | ||
--- | ||
|
||
Flow JS Testing now exports [`SignatureAlgorithm`](/docs/api.md#signaturealgorithm) and [`HashAlgorithm`](/docs/api.md#hashalgorithm) which are enums that may be used with [`createAccount`](/docs/accounts.md#createaccountname-keys) and [`sendTransaction`](/docs/send-transactions.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@onflow/flow-js-testing": minor | ||
--- | ||
|
||
Flow JS Testing now exports the [`pubFlowKey`](/docs/api.md#pubflowkeykeyobject) method which may be used to generate an RLP-encoded `Buffer` representing a public key corresponding to a particular private key. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@onflow/flow-js-testing": minor | ||
--- | ||
|
||
Flow JS Testing now exports the [`createAccount`](/docs/accounts.md#createaccountname-keys) method which may be used to manually create an account with a given human-readable name & specified keys. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,21 @@ | ||
import FlowManager from 0x01 | ||
|
||
transaction (_ name: String, pubKey: String, manager: Address) { | ||
transaction (_ name: String?, pubKey: [String], manager: Address) { | ||
prepare( admin: AuthAccount) { | ||
let newAccount = AuthAccount(payer:admin) | ||
newAccount.addPublicKey(pubKey.decodeHex()) | ||
for key in pubKey { | ||
newAccount.addPublicKey(key.decodeHex()) | ||
} | ||
|
||
let linkPath = FlowManager.accountManagerPath | ||
let accountManager = getAccount(manager) | ||
.getCapability(linkPath)! | ||
.borrow<&FlowManager.Mapper>()! | ||
|
||
// Create a record in account database | ||
let address = newAccount.address | ||
accountManager.setAddress(name, address: address) | ||
if name != nil { | ||
let linkPath = FlowManager.accountManagerPath | ||
let accountManager = getAccount(manager) | ||
.getCapability(linkPath)! | ||
.borrow<&FlowManager.Mapper>()! | ||
|
||
// Create a record in account database | ||
let address = newAccount.address | ||
accountManager.setAddress(name!, address: address) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import path from "path" | ||
import { | ||
emulator, | ||
init, | ||
getAccountAddress, | ||
executeScript, | ||
createAccount, | ||
HashAlgorithm, | ||
SignatureAlgorithm, | ||
} from "../src" | ||
import {playgroundImport} from "../src/transformers" | ||
import * as fcl from "@onflow/fcl" | ||
import {validateKeyPair} from "./util/validate-key-pair" | ||
import {permute} from "./util/permute" | ||
import {isAddress} from "../src" | ||
|
||
beforeEach(async () => { | ||
const basePath = path.resolve(__dirname, "./cadence") | ||
await init(basePath) | ||
return emulator.start() | ||
}) | ||
|
||
afterEach(async () => { | ||
emulator.stop() | ||
}) | ||
|
||
it("createAccount - should work with name and resolves to correct getAccountAddress", async () => { | ||
const addr1 = await createAccount({ | ||
name: "Billy", | ||
}) | ||
|
||
const addr2 = await getAccountAddress("Billy") | ||
|
||
expect(addr1).toBe(addr2) | ||
}) | ||
|
||
it("createAccount - should work without name and returns address", async () => { | ||
const Billy = await createAccount({ | ||
name: "Billy", | ||
}) | ||
|
||
expect(isAddress(Billy)).toBe(true) | ||
}) | ||
|
||
test.each(permute(Object.keys(HashAlgorithm), Object.keys(SignatureAlgorithm)))( | ||
"createAccount - should work with custom keys - hash algorithm %s - signing algorithm %s", | ||
async (hashAlgorithm, signatureAlgorithm) => { | ||
const privateKey = "1234" | ||
const Billy = await createAccount({ | ||
name: "Billy", | ||
keys: [ | ||
{ | ||
privateKey, | ||
hashAlgorithm: HashAlgorithm[hashAlgorithm], | ||
signatureAlgorithm: SignatureAlgorithm[signatureAlgorithm], | ||
}, | ||
], | ||
}) | ||
|
||
expect(isAddress(Billy)).toBe(true) | ||
|
||
const keys = await fcl.account(Billy).then(d => d.keys) | ||
|
||
expect(keys.length).toBe(1) | ||
expect(keys[0].hashAlgoString).toBe(hashAlgorithm) | ||
expect(keys[0].signAlgoString).toBe(signatureAlgorithm) | ||
expect(keys[0].weight).toBe(1000) | ||
expect( | ||
validateKeyPair(keys[0].publicKey, privateKey, signatureAlgorithm) | ||
).toBe(true) | ||
} | ||
) | ||
|
||
test("createAccount - should work with custom keys - defaults to SHA3_256, ECDSA_P256", async () => { | ||
const privateKey = "1234" | ||
const Billy = await createAccount({ | ||
name: "Billy", | ||
keys: [ | ||
{ | ||
privateKey, | ||
}, | ||
], | ||
}) | ||
|
||
expect(isAddress(Billy)).toBe(true) | ||
|
||
const keys = await fcl.account(Billy).then(d => d.keys) | ||
|
||
expect(keys.length).toBe(1) | ||
expect(keys[0].hashAlgoString).toBe("SHA3_256") | ||
expect(keys[0].signAlgoString).toBe("ECDSA_P256") | ||
expect(keys[0].weight).toBe(1000) | ||
expect( | ||
validateKeyPair( | ||
keys[0].publicKey, | ||
privateKey, | ||
SignatureAlgorithm.ECDSA_P256 | ||
) | ||
).toBe(true) | ||
}) | ||
|
||
it("createAccount - should add universal private key to account by default", async () => { | ||
const Billy = await createAccount({ | ||
name: "Billy", | ||
}) | ||
|
||
expect(isAddress(Billy)).toBe(true) | ||
}) | ||
|
||
it("getAccountAddress - should return proper playground addresses", async () => { | ||
const accounts = ["Alice", "Bob", "Charlie", "Dave", "Eve"] | ||
for (const i in accounts) { | ||
await getAccountAddress(accounts[i]) | ||
} | ||
|
||
const code = ` | ||
pub fun main(address:Address):Address{ | ||
return getAccount(address).address | ||
} | ||
` | ||
|
||
const playgroundAddresses = ["0x01", "0x02", "0x03", "0x04", "0x05"] | ||
for (const i in playgroundAddresses) { | ||
const [result] = await executeScript({ | ||
code, | ||
transformers: [playgroundImport(accounts)], | ||
args: [playgroundAddresses[i]], | ||
}) | ||
const account = await getAccountAddress(accounts[i]) | ||
expect(result).toBe(account) | ||
} | ||
}) | ||
|
||
it("getAccountAddress - should create an account if does not exist", async () => { | ||
const Billy = await getAccountAddress("Billy") | ||
|
||
expect(isAddress(Billy)).toBe(true) | ||
}) | ||
|
||
it("getAccountAddress - should resolve an already created account", async () => { | ||
const Billy1 = await getAccountAddress("Billy") | ||
const Billy2 = await getAccountAddress("Billy") | ||
|
||
expect(isAddress(Billy1)).toBe(true) | ||
expect(Billy1).toMatch(Billy2) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export const permute = (...values) => | ||
values.length > 1 | ||
? permute( | ||
values[0].reduce((acc, i) => { | ||
return [...acc, ...values[1].map(j => [].concat(i).concat(j))] | ||
}, []) | ||
) | ||
: values[0] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import {ec as EC} from "elliptic" | ||
import { | ||
resolveSignAlgoKey, | ||
SignAlgoECMap, | ||
SignatureAlgorithm, | ||
} from "../../src/crypto" | ||
import {isString} from "../../src/utils" | ||
|
||
export function validateKeyPair( | ||
publicKey, | ||
privateKey, | ||
signatureAlgorithm = SignatureAlgorithm.P256 | ||
) { | ||
const signAlgoKey = resolveSignAlgoKey(signatureAlgorithm) | ||
const curve = SignAlgoECMap[signAlgoKey] | ||
|
||
const prepareKey = key => { | ||
if (isString(key)) key = Buffer.from(key, "hex") | ||
if (key.at(0) !== 0x04) key = Buffer.concat([Buffer.from([0x04]), key]) | ||
return key | ||
} | ||
|
||
publicKey = prepareKey(publicKey) | ||
privateKey = prepareKey(privateKey) | ||
|
||
const ec = new EC(curve) | ||
const pair = ec.keyPair({ | ||
pub: publicKey, | ||
priv: privateKey, | ||
}) | ||
|
||
return pair.validate()?.result ?? false | ||
} |
Oops, something went wrong.