Movement support on Turnkey
examples/with-movement
: demonstrates transaction construction and broadcast on Movement.import { Turnkey } from "@turnkey/sdk-server";
import {
MovementClient,
AptosAccount,
TxnBuilderTypes,
BCS,
HexString
} from "movement-sdk";
// Custom Turnkey signer for Movement
class TurnkeyMovementSigner {
private turnkeyClient: Turnkey;
private movementClient: MovementClient;
private address: string;
private organizationId: string;
constructor(
apiPrivateKey: string,
apiPublicKey: string,
organizationId: string,
address: string,
nodeUrl: string = "https://seed-node1.movementlabs.xyz"
) {
this.turnkeyClient = new Turnkey({
apiBaseUrl: "https://api.turnkey.com",
apiPrivateKey,
apiPublicKey,
defaultOrganizationId: organizationId
});
this.movementClient = new MovementClient(nodeUrl);
this.address = address;
this.organizationId = organizationId;
}
// Get the account address
getAddress(): string {
return this.address;
}
// Sign a raw payload using Turnkey
async signRawPayload(payload: Uint8Array): Promise<Uint8Array> {
const hexPayload = Buffer.from(payload).toString('hex');
const signResult = await this.turnkeyClient.signRawPayload({
organizationId: this.organizationId,
signWith: this.address,
payload: hexPayload,
encoding: "hex"
});
return Buffer.from(signResult.signature, 'hex');
}
// Submit a transaction to Movement
async submitTransaction(payload: any): Promise<string> {
try {
// Get account info for sequence number
const accountInfo = await this.movementClient.getAccount(this.address);
const sequenceNumber = BigInt(accountInfo.sequence_number);
// Get chain ID for the transaction
const chainId = await this.movementClient.getChainId();
// Build raw transaction
const rawTx = new TxnBuilderTypes.RawTransaction(
// Account address
TxnBuilderTypes.AccountAddress.fromHex(this.address),
// Sequence number
sequenceNumber,
// Transaction payload
payload,
// Max gas
BigInt(10000),
// Gas unit price
BigInt(100),
// Expiration timestamp (30 seconds from now)
BigInt(Math.floor(Date.now() / 1000) + 30),
// Chain ID
new TxnBuilderTypes.ChainId(chainId)
);
// Serialize the transaction
const serializer = new BCS.Serializer();
rawTx.serialize(serializer);
const toSign = serializer.getBytes();
// Sign the transaction
const signature = await this.signRawPayload(toSign);
// In a real implementation, you would need the actual public key from the address
// Here we use a placeholder
const dummyPublicKey = new TxnBuilderTypes.Ed25519PublicKey(new Uint8Array(32));
// Create authenticator
const authenticator = new TxnBuilderTypes.TransactionAuthenticatorEd25519(
dummyPublicKey,
new TxnBuilderTypes.Ed25519Signature(signature)
);
// Create signed transaction
const signedTx = new TxnBuilderTypes.SignedTransaction(
rawTx,
authenticator
);
// Submit transaction
const txnResponse = await this.movementClient.submitTransaction(
BCS.bcsToBytes(signedTx)
);
return txnResponse.hash;
} catch (error) {
console.error("Error submitting transaction:", error);
throw error;
}
}
}
// Example usage: Transfer MOV tokens
async function transferMovTokens() {
const signer = new TurnkeyMovementSigner(
process.env.API_PRIVATE_KEY!,
process.env.API_PUBLIC_KEY!,
process.env.ORGANIZATION_ID!,
process.env.MOVEMENT_ADDRESS!, // Your Movement address in Turnkey
"https://testnet.movementlabs.xyz" // Use testnet URL for development
);
const recipientAddress = "0x..."; // Recipient address
const amount = 1000000; // Amount (adjust decimal places as needed)
// Create a transfer transaction payload
const payload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
TxnBuilderTypes.EntryFunction.natural(
"0x1::coin",
"transfer",
[new TxnBuilderTypes.TypeTagStruct(
TxnBuilderTypes.StructTag.fromString("0x1::mov_coin::MOV")
)],
[
BCS.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex(recipientAddress)),
BCS.bcsSerializeUint64(amount)
]
)
);
try {
const txnHash = await signer.submitTransaction(payload);
console.log(`Transaction submitted successfully! Hash: ${txnHash}`);
return txnHash;
} catch (error) {
console.error("Error transferring tokens:", error);
throw error;
}
}
## Movement Network Support
Turnkey supports:
* Movement Mainnet
* Movement Testnet
## Key Features for Movement
* **Ed25519 Signing**: Turnkey fully supports the Ed25519 curve used by Movement
* **BCS Format Support**: Sign transactions serialized in the Binary Canonical Serialization format
* **Integration Example**: Our example repository provides a reference implementation for integrating with the Movement ecosystem
## Benefits of Using Turnkey with Movement
* **Secure Private Keys**: Keys are securely stored in Turnkey's infrastructure
* **Customizable Policies**: Implement rules to control when and how transactions are signed
* **Developer-Friendly**: Seamless integration with existing Movement development workflows
* **Enterprise-Ready**: Built for production environments with high security requirements
## Move Smart Contract Development
Movement leverages the Move VM for smart contracts. When developing Move smart contracts on Movement, Turnkey can securely manage your private keys for:
* Deploying Move modules
* Publishing packages
* Executing Move functions
* Managing on-chain resources
If you're building on Movement and need assistance with your Turnkey integration, feel free to contact us at [hello@turnkey.com](mailto:hello@turnkey.com), on [X](https://x.com/turnkeyhq/), or [on Slack](https://join.slack.com/t/clubturnkey/shared_invite/zt-31v4yhgw6-PwBzyNsWCCBTk2xft3EoHQ).