@civic/sol-did-client
Version:
A powerful DID-method on Solana
219 lines • 9 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DidSolTransactionBuilder = exports.DidSolEthSignStatusType = void 0;
const web3_js_1 = require("@solana/web3.js");
const anchor_1 = require("@coral-xyz/anchor");
const utils_1 = require("../lib/utils");
const const_1 = require("../lib/const");
const DidAccountSizeHelper_1 = require("../DidAccountSizeHelper");
var DidSolEthSignStatusType;
(function (DidSolEthSignStatusType) {
DidSolEthSignStatusType[DidSolEthSignStatusType["NotSupported"] = 0] = "NotSupported";
DidSolEthSignStatusType[DidSolEthSignStatusType["Unsigned"] = 1] = "Unsigned";
DidSolEthSignStatusType[DidSolEthSignStatusType["Signed"] = 2] = "Signed";
})(DidSolEthSignStatusType || (exports.DidSolEthSignStatusType = DidSolEthSignStatusType = {}));
/**
*
*/
class DidSolTransactionBuilder {
constructor(_wallet, _connection, _confirmOptions, idl, _partialSigners = [], _ethSigner, _payer, _resizeAuthority = _wallet.publicKey) {
this._wallet = _wallet;
this._connection = _connection;
this._confirmOptions = _confirmOptions;
this._partialSigners = _partialSigners;
this._ethSigner = _ethSigner;
this._payer = _payer;
this._resizeAuthority = _resizeAuthority;
// General instructions (that modify the account state only).
this._generalInstructions = [];
// Generic Instructions that are appended to the instuction list
this._postInstructions = [];
this._initialWallet = _wallet;
this._idlErrors = (0, anchor_1.parseIdlErrors)(idl);
}
get solWallet() {
return this._wallet;
}
get connection() {
return this._connection;
}
get confirmOptions() {
return this._confirmOptions;
}
get ethSigner() {
return this._ethSigner;
}
withEthSigner(ethSigner) {
this._ethSigner = ethSigner;
return this;
}
setInitInstruction(initInstruction) {
if (this._initInstruction) {
throw new Error('Init instruction already set.');
}
this._initInstruction = initInstruction;
}
setResizeInstruction(resizeInstruction) {
if (this._resizeInstruction) {
throw new Error('Resize instruction already set.');
}
this._resizeInstruction = resizeInstruction;
}
setCloseInstruction(closeInstruction) {
if (this._closeInstruction) {
throw new Error('Close instruction already set.');
}
this._closeInstruction = closeInstruction;
}
addGeneralInstruction(instruction) {
this._generalInstructions.push(instruction);
}
addPostInstruction(instruction) {
this._postInstructions.push(instruction);
}
/**
* Clears all prepared Instructions and partialSigners, ethWallet, payer and resizeAuthority.
*/
clear() {
this.clearInstructions();
this._wallet = this._initialWallet;
this._partialSigners = [];
this._ethSigner = undefined;
this._payer = undefined;
this._resizeAuthority = this._wallet.publicKey;
}
clearInstructions() {
this._initInstruction = undefined;
this._resizeInstruction = undefined;
this._closeInstruction = undefined;
this._generalInstructions = [];
this._postInstructions = [];
}
withConnection(connection) {
this._connection = connection;
return this;
}
withConfirmOptions(confirmOptions) {
this._confirmOptions = confirmOptions;
return this;
}
withSolWallet(wallet) {
this._wallet = wallet;
return this;
}
withAutomaticAlloc(payer, resizeAuthority = this._wallet.publicKey) {
this._payer = payer;
this._resizeAuthority = resizeAuthority;
return this;
}
withPartialSigners(...signers) {
this._partialSigners = signers;
return this;
}
/**
* Signs a supported DidSol Instruction with an Ethereum Signer.
*/
ethSignInstructions(instructionsToSign) {
return __awaiter(this, void 0, void 0, function* () {
let lastNonce = yield this.getNonce();
const promises = instructionsToSign.map((instruction) => __awaiter(this, void 0, void 0, function* () {
if (!this.ethSigner ||
instruction.ethSignStatus !== DidSolEthSignStatusType.Unsigned) {
return instruction.instructionPromise;
}
const signingNonce = lastNonce;
lastNonce = lastNonce.addn(1);
return (0, utils_1.ethSignPayload)(yield instruction.instructionPromise, signingNonce, this.ethSigner);
}));
// Mix in _postInstructions to array. Consider moving to cleaner position
return Promise.all([...promises, ...this._postInstructions]);
});
}
getMaxRequiredSize(currentAccount, currentSize) {
let current = [currentAccount, currentSize];
let maxSize = currentSize;
for (const instruction of this._generalInstructions) {
current = instruction.didAccountChangeCallback(current[0], current[1]);
maxSize = Math.max(maxSize, current[1]);
}
return maxSize;
}
setAllocInstruction() {
return __awaiter(this, void 0, void 0, function* () {
if (!this._payer || this._generalInstructions.length === 0) {
return;
}
const [didAccount, didAccountSize] = yield this.getDidAccountWithSize();
if (didAccount === null) {
// Initial allocation
const requiredSize = this.getMaxRequiredSize((0, DidAccountSizeHelper_1.getDefaultRawDidSolDataAccount)(this.didDataAccount), const_1.INITIAL_MIN_ACCOUNT_SIZE);
this.initialize(requiredSize, this._payer);
}
else {
// Reallocation
const requiredSize = this.getMaxRequiredSize(didAccount.raw, DidAccountSizeHelper_1.DidAccountSizeHelper.fromAccount(didAccount.raw).getTotalNativeAccountSize());
if (didAccountSize < requiredSize) {
this.resize(requiredSize, this._payer, this._resizeAuthority);
}
}
});
}
// Terminal Instructions
instructions() {
return __awaiter(this, void 0, void 0, function* () {
// check if additional alloc instructions are needed.
yield this.setAllocInstruction();
const instructionChain = [];
if (this._initInstruction) {
instructionChain.push(this._initInstruction);
}
if (this._resizeInstruction) {
instructionChain.push(this._resizeInstruction);
}
instructionChain.push(...this._generalInstructions);
if (this._closeInstruction) {
instructionChain.push(this._closeInstruction);
}
// ethSign
const finalInstructions = yield this.ethSignInstructions(instructionChain);
// needs to be the last method.
this.clearInstructions();
return finalInstructions;
});
}
transaction() {
return __awaiter(this, void 0, void 0, function* () {
const tx = new web3_js_1.Transaction();
const instructions = yield this.instructions();
// console.log(JSON.stringify(instructions, null, 2));
tx.add(...instructions);
return tx;
});
}
rpc(opts) {
return __awaiter(this, void 0, void 0, function* () {
const provider = new anchor_1.AnchorProvider(this._connection, this._wallet, this._confirmOptions);
try {
const tx = yield this.transaction();
return yield provider.sendAndConfirm(tx, this._partialSigners, opts);
}
catch (err) {
throw (0, anchor_1.translateError)(err, this._idlErrors);
}
finally {
this.clear();
}
});
}
}
exports.DidSolTransactionBuilder = DidSolTransactionBuilder;
//# sourceMappingURL=DidSolTransactionBuilder.js.map