[to be continued] How do I send a Blob from JS frontend to Motoko backend?

How do I send a Blob from JS frontend to Motoko backend? was not settled for me.So I want to continue.

I use ext-token: erc721.mo, but error.
My thought for this error is directly metadata type because there is

if (!t.covariant(x)) {throw new Error.....} //at Module.encode (index.js:4522:75)

I have tried way that match Blob type in motoko in link like a using new Unit8Array.
But may be different points. I don’t know… I want to do without this error!!

index.js:4524 Uncaught (in promise) Error: Invalid record {to:variant {principal:principal; address:text}; metadata:opt vec nat8} argument: {"to":{"principal":{"_arr":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":1,"8":1,"9":1},"_isPrincipal":true},"address":"test"},"metadeta":[97,98,99,100]}  //metadata is changed from string of "abcd" in input form
    at index.js:4524:19
    at index.js:3435:29
    at Array.map (<anonymous>)
    at zipWith (index.js:3435:15)
    at Module.encode (index.js:4522:75)
    at caller (index.js:199:74)
    at CanisterActor.handler [as mintNFT] (index.js:221:34)
    at HTMLButtonElement.<anonymous> (index.js:17799:99)

My front-end code(index.js)

import { dfinity_nft_ext } from "../../declarations/dfinity_nft_ext";
document.getElementById("mintNftBtn").addEventListener("click", async () => {

  const nft = document.getElementById("nft").value.toString();
  const blob = new Blob([nft], {type: 'text/html'});
  const arrayBuffer = [...new Uint8Array(await blob.arrayBuffer())];
  const minter = await dfinity_nft_ext.getMinter();
  console.log("miner::::"+minter);
  const mintReq = {
    to: { principal: minter, address: "test" }, //minter is owner of mint, address is properness
    metadeta: arrayBuffer
  };
  const minted = await dfinity_nft_ext.mintNFT(mintReq);  // mint
  console.log("minted::::"+minted);  //Maybe return minted number
});
4 Likes

I don’t think this is right. to is variant, which means it should be either principal or address, can’t be both.
so you might to try:

to: { principal: minter},

2 Likes

Thank you for reply.
Unfortunally, come up next error.

Uncaught (in promise) Error: Record is missing key "metadata".

My thought is deleting address in to key cause Object style’s wrong, or metadata key lost something happen.

It would be very helpful if you could let me know.Tnank you in advance.

mintNFT argument ‘MintRequest’ is here.

public type MintRequest = {
    to : ExtCore.User;
    metadata : ?Blob;
  };

ExtCore.User is

public type User = {
    #address : AccountIdentifier; //No notification
    #principal : Principal; //defaults to sub account 0
  };
1 Like

I guess it’s typo :grinning: metadata , not metadeta

1 Like

Oh, that is shame! :smiley:

Unfortunally, an error at first came back after changing typo.I don’t want to take your time.But,I want to know why.I will write article in Japanese if I can get through.So I need to help.At first, what I did is for an error of Error: Invalid record

change principal type
Variant minter have two “_arr” and “_isPrincipal” in Object, so chaged minter to “rrkah-fqaaa-aaaaa-aaaaq-cai” hard code.
Result
doesnt change, same error.
confirmation
metadate type is Blob in backend. Corresponding JavaScript values => [ 1, 2, 3, 4, … ] in Type Blob in Document.
metadate type seems OK as long as I see front-end’s input value.

Then, what point is it in this error of covariant(x) {throw new Error}?Covariant means “match” simply saying?
My thought is front-end type doesn’t match back-end’s. But,I feel this is clear.What should I check next?
Thank you in advance.

1 Like

はじめまして、@ueyamamasashi さん。

Please forgive me if my greeting is incorrect. This is my first time trying to use Japanese in an online context.

The covariant error suggests that you are providing a value of the wrong type somewhere.

Please could you share your updated code with the typos fixed, and the latest error along with the stack trace?

2 Likes

If you want hardcore, need wrap it to Principal type : Principal.fromText(“rrkah-fqaaa-aaaaa-aaaaq-cai”)

and it looks like this is a canister id, not sure if there is a validate for it, so you might use a real “user” principal for test first.

1 Like

Thank you for your kindness.It is very helpful for beginner like me.
But, hurdle is very high as you say that wrap to Principal type.I tried, but I feel I shouldn’t do that.
Yes, this is canister id. I confuse principal id and canister id because both of types is same Principal.I try hard to learn more.
I keep going forward I will close this question.
Thank you again!!

はじめまして :innocent: yes, correct!

Thank you for reply. I am so glad to get reply, you and your team are so kind. I am one of Japanese Dfinity team.We will make open source code for NFT etc. But, my skill is not enough for this.
This time, my error is coming from wrong type as you teach me, but I don’t know where I bring principal id from.
Here is stack trace. I don’t know well so I put images not only concole but source.
console(chrome validation)


** source**(chrome validation)

my code(index.js)

const mintReq = {
    to: {
      principal: "iuj24-a5hic-jrod4-5oq3e-artpl-6khow-3sly6-4nonf-d2pjr-emp2g-kqe" }, 
      metadata: arrayBuffer
  };
  const minted = await dfinity_nft_ext.mintNFT(mintReq);  // mint

Principal Id is result of command dfx identity get-principal(I think type is matched)

1 Like

Please give this a try:

const mintReq = {
  to: {
    principal: Principal.fromText("iuj24-a5hic-jrod4-5oq3e-artpl-6khow-3sly6-4nonf-d2pjr-emp2g-kqe")
  },
  metadata: arrayBuffer
};
const minted = await dfinity_nft_ext.mintNFT(mintReq);  // mint
2 Likes

Thank you very much. But I got not a function error.

No typo this time. → did manytime
Made sure Principal.fromText is function. → func fromText(t : Text) : Principal

Did I make sure module of “@dfinity/candid/lib/cjs/idl”, didn’t I?

What should I do next?

1 Like

metadata needs optional type.

1 Like

I think you need to import from @dfinity/principal

2 Likes

Still does not work here is my code

let mintNFT = async (_minter, _metadata) => {
  const mintReq = {
    to: { principal: _minter },
    metadata: _metadata,
  };
  res = await actor.mintNFT(mintReq).catch((e) => {
    return "Error" + e;
  });
  return res;
};

let text = "asdcxzvuioashnuid";
let arr = [...new Uint8Array(Buffer.from(text, "utf-8"))];
mintNFT(Principal.fromText("2vxsx-fae"), arr).then((res) => {
  console.log(res);
});

the error result is like
ErrorError: Invalid record {to:variant {principal:principal; address:text}; metadata:opt vec nat8} argument: {"to":{"principal":{"_arr":{"0":4},"_isPrincipal":true}},"metadata":[97,115,100,99,120,122,118,117,105,111,97,115,104,110,117,105,100]}

btw this works

  const mintReq = {
    to: { principal: _minter },
    metadata: [],
  };

So I guess is the problem of nat8?

Problem resolved. Since the require ?Blob rather than Blob. the metadata should be metadata: [[...new Uint8Array(Buffer.from("asdcxzvuioashnuid", "utf-8"))]]

Type opt t

Corresponding JavaScript values
null translates to [].

opt 8 translates to [8].

opt opt "test" translates to [["test"]].
3 Likes

I was stuck with it, unable to resolve it.
Thanks. :pray:

1 Like