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

Deprecate Params #177

Closed
7 tasks done
orodio opened this issue Jul 14, 2020 · 0 comments
Closed
7 tasks done

Deprecate Params #177

orodio opened this issue Jul 14, 2020 · 0 comments
Assignees
Labels

Comments

@orodio
Copy link
Contributor

orodio commented Jul 14, 2020

We are wanting to remove the current param mechanism from the sdk. Due to our commitment to backwards compatibility, this issue is mostly about adding deprecation warnings when params are used and how to migrate away from them.

Background

Currently we can write a script like this using params:

function add(a, b, message) {
  return fcl.send([
    fcl.script`
      pub fun main(): Int {
        log("${p => p.msg}")
        return ${p => p.a} + ${p => p.b}
      }
    `,
    fcl.params([
      fcl.param(a, t.Identity, "a"),
      fcl.param(b, t.Identity, "b"),
      fcl.param(message, t.Identity, "msg")
    ])
  ])
}

add(5, 6)
  .then(fcl.decode)
  .then(value => assert(value === 5 + 6)) // true

Originally we were hoping to gracefully transition this into the arguments (which were recently added), thinking that people would only need injection style interop or interaction level arguments, but this line of thought proved to be incorrect. We now understand that what the consumer needs is arguments for user input to scripts and transactions, and being able to dynamically change the script/transaction given some sort of external value that is completely in control of the consumer, all of which we can already do.

Injection style interop (params) is also quite tricky. It is susceptible to injection attacks (where the value escapes the current expression, does its own malicious expression, continues on as if nothing happend), the user is responsible for making sure the cadence is valid. For example: log(${p => p.imAString}) would break because the string isn't wrapped in quotes and would have to be written like: log("${p => p.imAString}"), a subtle but devastating issue if missed.

Also the code example above can be done a couple other ways.

First as arguments (the preferred way) which has the following benefits

  • not susceptible to inject attacks via input as it is typed, and checked by the Cadence VM
  • no need for thinking about stuff like "do i need to wrap this in quotes".
function add(a, b, message) {
  return fcl.send([
    fcl.script`
      pub fun main(a: Int, b: Int): Int {
        return a + b
      }
    `,
    fcl.args([
      fcl.arg(a, t.Int),
      fcl.arg(b, t.Int),
    ])
  ])
}
// original assert should still hold true

As standard string interop. This has many of the original issues with params, but it is way less complex, closer to what people understand as standard javascript, and is more obvious that the users are responsible for making sure the values once injected into the cadence is valid. (I think its also easier to read and understand the intent than the params)

function add(a, b, message) {
  return fcl.send([
    fcl.script`
      pub fun main(): Int {
        log("${message}")
        return ${a} + ${b}
      }
    `
  ])
}
// original assert should still hold true

As a mix of the above.
The case for this one would be where the message is in control of the dapp (consumer) while the user of the dapp is in control of a and b. Pros and Cons of the above two examples also apply to this one.

function add(a, b, message) {
  return fcl.send([
    fcl.script`
      pub fun main(a: Int, b: Int): Int {
        log("${message}")
        return a + b
      }
    `,
    fcl.args([
      fcl.arg(a, t.Int),
      fcl.arg(b, t.Int),
    ])
  ])
}

Expected Outcome

Transition documentation

  • How to migrate from current params to arguments and standard interop
  • Examples of params vs arguments vs standard interop

Display deprecation notices with transition documentation when

  • fcl.params is called
  • When a function is interopped into the template literal ${p => p.a}

Documentation on when to use arguments vs standard interop

  • when to use arguments
  • when to user standard interop

Stretch Outcome

  • Display deprecation notices when a value is accessed on the params object (maybe using a proxy?)
@orodio orodio self-assigned this Jul 14, 2020
@orodio orodio added Current Sprint 🚀 Flow-JS-SDK Maintainers are working on this. and removed P-High S-JS-SDK labels Jul 16, 2020
@orodio orodio added the JS label Jul 24, 2020
@orodio orodio added Current Sprint 🚀 Flow-JS-SDK Maintainers are working on this. and removed Current Sprint 🚀 Flow-JS-SDK Maintainers are working on this. labels Jul 27, 2020
@orodio orodio closed this as completed Aug 7, 2020
@orodio orodio removed the Current Sprint 🚀 Flow-JS-SDK Maintainers are working on this. label Aug 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant