Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ownership provider to work with Lumos #127

Merged
merged 33 commits into from
Apr 10, 2023
Merged

feat: ownership provider to work with Lumos #127

merged 33 commits into from
Apr 10, 2023

Conversation

homura
Copy link
Contributor

@homura homura commented Mar 14, 2023

  • injectCapacity
  • payFee
  • collector
  • signTransaction

update(2023-03-20):

  • we should change constructor from {ckb: InjectedCkb} to {ckb: InjectedCkb , rpcUrl: string } since the ScriptConfig is required for the Provider
    async function loadSecp256k1ScriptDep(payload: { nodeUrl: string }): Promise<ScriptConfig> {
    const genesisBlock = await createRpcClient(payload.nodeUrl).request<RpcType.Block>('get_block_by_number', ['0x0']);
    if (!genesisBlock) throw new Error("can't load genesis block");
    const secp256k1DepTxHash = genesisBlock.transactions[1].hash;
    asserts.asserts(secp256k1DepTxHash, "can't load secp256k1 transaction");
    const rawTypeScript = genesisBlock.transactions[0].outputs[1].type;
    asserts.asserts(rawTypeScript, "can't load secp256k1 type script");
    const typeScript: Script = {
    codeHash: rawTypeScript.code_hash,
    hashType: rawTypeScript.hash_type,
    args: rawTypeScript.args,
    };
    const secp256k1TypeHash = utils.computeScriptHash(typeScript);
    return {
    HASH_TYPE: 'type',
    CODE_HASH: secp256k1TypeHash,
    INDEX: '0x0',
    TX_HASH: secp256k1DepTxHash,
    DEP_TYPE: 'depGroup',
    };
    }

🐤 Download canary assets:

nexus--canary.127.4635976068.zip

@codecov
Copy link

codecov bot commented Mar 14, 2023

Codecov Report

Merging #127 (a0ec159) into main (5543361) will decrease coverage by 1.05%.
The diff coverage is 81.25%.

@@            Coverage Diff             @@
##             main     #127      +/-   ##
==========================================
- Coverage   87.25%   86.20%   -1.05%     
==========================================
  Files          48       43       -5     
  Lines         816      870      +54     
  Branches       97      113      +16     
==========================================
+ Hits          712      750      +38     
+ Misses         21       20       -1     
- Partials       83      100      +17     
Impacted Files Coverage Δ
...s/ownership-providers/src/FullOwnershipProvider.ts 81.05% <81.05%> (ø)
packages/ownership-providers/src/index.ts 100.00% <100.00%> (ø)

... and 14 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@homura homura changed the base branch from main to protocol March 14, 2023 09:34
import produce from 'immer';

declare const recipient: Script;
declare const provider: FullOwnershipProvider;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to get the provider instance? it seems to be:

const provider = new FullOwnershipProvider(globalThis.ckb)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new FullOwnershipProvider({ ckb: globalThis.ckb })

we can check out from FullOwnershipProvider.ts

import { BIish } from '@ckb-lumos/bi';
import produce from 'immer';

declare const recipient: Script;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An idea: a test case can be based on this example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, this example is suitable as a case for integration testing, but I think it may be less suitable as a unit test case

@IronLu233
Copy link
Contributor

I want to reuse lumos prepare signing entries method.
https://github.com/ckb-js/lumos/blob/e73ca0502b0feb3e98be848f76325a912052d0f0/packages/common-scripts/src/helper.ts#L186-L279

Thus, my code will seems like

  /**
   * request wallet to sign a transaction skeleton
   * @param txSkeleton The transaction skeleton, you can create it from transaction object via `@ckb-lumos` {@link createTransactionFromSkeleton}
   * @returns The signed transaction skeleton. To get the signed transaction object, please use {@link sealTransaction} with empty sealingContents(`[ ]`).
   */
  async signTransaction(txSkeleton: TransactionSkeletonType): Promise<TransactionSkeletonType> {
    const config = getConfigFromRpcUrl();

    prepareSigningEntries(txSkeleton, config);
    const groupedSignature = await this.ckb.request({
      method: 'wallet_fullOwnership_signTransaction',
      params: { tx: createTransactionFromSkeleton(txSkeleton) },
    });

    txSkeleton = txSkeleton.update('witnesses', (witnesses) => {
      return witnesses.map((witness, index) => {
        const [, signature] = groupedSignature[index];
        if (!signature) return witness;
        const witnessArgs = WitnessArgs.unpack(witness);
        return bytes.hexify(
          WitnessArgs.pack({
            ...witnessArgs,
            lock: signature,
          }),
        );
      });
    });

    txSkeleton = txSkeleton.update('signingEntries', (signingEntries) =>
      signingEntries.splice(0, groupedSignature.length),
    );

    return txSkeleton;
  }

@IronLu233 IronLu233 marked this pull request as ready for review March 22, 2023 08:04
});
});

txSkeleton = txSkeleton.update('signingEntries', (signingEntries) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to clear signingEntries here

return txSkeletonWithFee;
}

async *collector({ lock }: { lock?: Script } = {}): AsyncIterable<Cell> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pro usage, not easy to understand though

Base automatically changed from protocol to main March 23, 2023 08:49
@homura
Copy link
Contributor Author

homura commented Mar 24, 2023

Insufficient coverage of unit tests, can you add tests?

@IronLu233
Copy link
Contributor

can you try the coverage detection method mentioned in this post?

      <line num="138" count="10" type="cond" truecount="1" falsecount="0"/>

But it seems the coverage is wrong. jest tells me the if statement is full covered.

image

@IronLu233 IronLu233 force-pushed the ownership-provider branch from b1f980f to 2967fe4 Compare March 27, 2023 11:55
if ('payers' in options && options.payers?.length === 0 && !options.autoInject) {
errors.throwError('no payer is provided, but autoInject is `false`');
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should check if the fee is paid to avoid repeating fee payment

if (inputCapacitys - outputsCapacity >= neededFee) {
  return tx
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic of detecting if tx-fee is already paid: https://github.com/ckb-js/nexus/pull/127/files#diff-4212a8e65e25ac3827c0789664613414267d82d12237316f5b3adf09ac533476R209-R215

Is it better to run this logic before validating input parameters?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think validating parameter first is better.

Thinking the user give a invalid parameter, but because of detecting tx fee already paid, it is not throw.

It is not Intuitive.


// feeFromTransactionSize - (sum(inputsCapacity) - sum(outputsCapacity))
let requireFee = calculateFeeCompatible(currentTransactionSize, feeRate).sub(
sumCapacity(txSkeleton.get('inputs')).sub(sumCapacity(txSkeleton.get('outputs'))),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// FIXME detect if it is a DAO unlock transaction first

}

/**
* Pay the transaction fee using the specified lock
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// **NOT** support DAO unlock transaction yet, please consider using `lumos`'s `payFee`

@homura
Copy link
Contributor Author

homura commented Apr 6, 2023

@IronLu233 could you comment for the payFee does not support unlocking DAO transaction yet

@homura homura merged commit 0b9a242 into main Apr 10, 2023
@homura homura deleted the ownership-provider branch April 10, 2023 02:29
@github-actions
Copy link

🚀 PR was released in v0.0.10 🚀

@github-actions github-actions bot added the released This issue/pull request has been released. label Apr 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released This issue/pull request has been released.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants